Math is too complicated to understand, but it may be easier to read. Some of the variables were renamed to make more sense, and they were formatted to be simpler before your eyes.
function rate(paymentsPerYear, paymentAmount, presentValue, futureValue, dueEndOrBeginning, interest) { //If interest, futureValue, dueEndorBeginning was not set, set now if (interest == null) interest = 0.01; if (futureValue == null) futureValue = 0; if (dueEndOrBeginning == null) dueEndOrBeginning = 0; var FINANCIAL_MAX_ITERATIONS = 128;//Bet accuracy with 128 var FINANCIAL_PRECISION = 0.0000001;//1.0e-8 var y, y0, y1, x0, x1 = 0, f = 0, i = 0; var rate = interest; if (Math.abs(rate) < FINANCIAL_PRECISION) { y = presentValue * (1 + paymentsPerYear * rate) + paymentAmount * (1 + rate * dueEndOrBeginning) * paymentsPerYear + futureValue; } else { f = Math.exp(paymentsPerYear * Math.log(1 + rate)); y = presentValue * f + paymentAmount * (1 / rate + dueEndOrBeginning) * (f - 1) + futureValue; } y0 = presentValue + paymentAmount * paymentsPerYear + futureValue; y1 = presentValue * f + paymentAmount * (1 / rate + dueEndOrBeginning) * (f - 1) + futureValue; // find root by Newton secant method i = x0 = 0.0; x1 = rate; while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) { rate = (y1 * x0 - y0 * x1) / (y1 - y0); x0 = x1; x1 = rate; if (Math.abs(rate) < FINANCIAL_PRECISION) { y = presentValue * (1 + paymentsPerYear * rate) + paymentAmount * (1 + rate * dueEndOrBeginning) * paymentsPerYear + futureValue; } else { f = Math.exp(paymentsPerYear * Math.log(1 + rate)); y = presentValue * f + paymentAmount * (1 / rate + dueEndOrBeginning) * (f - 1) + futureValue; } y0 = y1; y1 = y; ++i; } return rate; }
source share