APR Calculator

1. Junior Member
Join Date
Dec 1969
Posts
3

## APR Calculator

I&#039;ve been doing a lot of surfing, but to no avail. I need an APR calculator, but the one&#039;s I&#039;ve been finding aren&#039;t taking the variables I want. I need to supply ONLY the cost, term, and monthly payment (doesn&#039;t change). I haven&#039;t found anything, but a calculus formula. I&#039;m VERY rusty, and have no chance with that. Here&#039;s the formula just in case:<BR><BR>Loan = P/(1+i)^a + P/(1+i)^b + P/(1+i)^c + ...<BR><BR>Where P is the monthly payment and a, b etc are the periods of the term, up to 24 usually. Anybody know of a script or ANYTHING using this method?

2. Senior Member
Join Date
Dec 1969
Posts
96,118

## Can't be done via math!

Believe it or not, you have to do it by "iteration".<BR><BR>That is, make a guess as to the interest rate and then find out what the payment amount would be for that interest rate and term and loan amount. If the payment is too high, test with a smaller interest rate. If too low, test with a higher interest rate. Keep doing that until you get the right rate.<BR><BR>Somewhere around here I&#039;ve got a loan calculator that I did all in JS/HTML that works pretty well. If I can find what I did with it, I&#039;ll post it.<BR><BR>Incidentally, that formula is correct, but it&#039;s easy to simplify the hell out of it.<BR><BR>Oh...just found at least one version of my calculator. This was done back in 2000 for a contest where each web page, including images *and* JavaScript, could not exceed 5K bytes. So it is necessarily cryptic, in order to keep the size down.<BR><BR>Hope you can decipher it. If not, I&#039;ll see if I have a bigger version floating around.<BR><BR>******** LoanCaclulator.html *********<BR>&lt;HTML&#062;&lt;HEAD&#062;&lt;TITLE &#062;Simple Loan Calculator&lt;/TITLE&#062;&lt;SCRIPT&#062;<BR>Z=new Array("PV","PMT","APR","PER");<BR>X=new Array("Loan amount","Payment amount","Note rate","Number of years");<BR>V=new Array(4);<BR>AW=null;AC=0;tw = 1200.0;<BR>var frm;<BR>function fF(i){return(1-Math.pow(1+i,-V[3]*12))/i;}<BR>function fA(){<BR> if(!(my = frm.AM.checked)&&!frm.AY.checked)return;<BR> if(AW!=null && !AW.closed)AW.close();<BR> AW=window.open("","Amortization"+(++AC),"resizable ,scrollbars,width="+(frm.RAW.checked?630:450));<BR > am=AW.document;<BR> am.write( "&lt;HTML&#062;&lt;HEAD&#062;&lt;TITLE&#062;Amorti zation Schedule&lt;/TITLE&#062;&lt;/HEAD&#062;"<BR> + "&lt;BODY&#062;&lt;CENTER&#062;&lt;H2&#062;Amortiz ation Schedule for This Loan:&lt;/H2&#062;
" <BR> + "&lt;TABLE Border=3 CellPadding=5 bgColor=lightGreen&#062;
" <BR> + "&lt;TR&#062;&lt;TD align=right&#062;Loan amount:&lt;/TD&#062;&lt;TD align=right&#062;" <BR> + fM(V[0]) + "&lt;/TD&#062;&lt;/TR&#062;
"<BR> + "&lt;TR&#062;&lt;TD align=right&#062;Loan payment:&lt;/TD&#062;&lt;TD align=right&#062;" <BR> + fM(V[1]) + "&lt;/TD&#062;&lt;/TR&#062;
"<BR> + "&lt;TR&#062;&lt;TD align=right&#062;Note rate:&lt;/TD&#062;&lt;TD align=right&#062;" <BR> + fM(V[2]) + "&lt;/TD&#062;&lt;/TR&#062;
"<BR> + "&lt;TR&#062;&lt;TD align=right&#062;Number of years:&lt;/TD&#062;&lt;TD align=right&#062;" <BR> + fM(V[3]) + "&lt;/TD&#062;&lt;/TR&#062;&lt;/TABLE&#062;&lt;HR&#062;
"<BR> + "&lt;TABLE Border=1 CellPadding=5 bgColor=lightBlue&#062;"<BR> + "&lt;TR&#062;&lt;TH&#062;"+(my?"Month":"Year")+"&l t;BR&#062;number&lt;/TH&#062;&lt;TH&#062;To interest&lt;/TH&#062;"<BR> + "&lt;TH&#062;To principal&lt;/TH&#062;&lt;TH&#062;Loan balance&lt;/TH&#062;&lt;/TR&#062;
"<BR> );<BR> bal=V[0];rt=V[2]/tw;cI=cP=0;cE=V[3]*12;<BR> nI=0<BR> for(var mn=1;mn&lt;=cE;++mn){nI+=(tI=bal*rt);cI+=tI;tP=V[1]-tI;cP+=tP;bal=bal-tP;<BR> if(my&#124&#124(mn%12)==0&#124&#124mn==cE){pn=my?m n:mn/12;<BR> am.write("&lt;TR&#062;&lt;TD&#062;"+pn+"&lt;/TD&#062;&lt;TD align=right&#062;"+fM(cI)+"&lt;/TD&#062;&lt;TD align=right&#062;"<BR> +fM(cP)+"&lt;/TD&#062;&lt;TD align=right&#062;"+fM(bal)+"&lt;/TD&#062;&lt;/TR&#062;
");<BR> cI=cP=0;}}<BR> am.write("&lt;TR&#062;&lt;TD colSpan=4 align=center&#062;Total interest paid: "+fM(nI)+"&lt;/TD&#062;&lt;/TR&#062;");<BR> am.write("&lt;/TABLE&#062;&lt;/BODY&#062;&lt;/HTML&#062;
");<BR>}<BR>function fM(sv){v=Math.abs(sv); <BR> if(frm.RAW.checked){return(v&lt;0.001)?"0.00":sv;} <BR> v=""+Math.round(v*100);dp=v.length-2;<BR> if(dp==-1)r="0.0"+v;<BR> else if(dp==0)r="0."+v;<BR> else r=v.substring(0,dp)+"."+v.substring(dp);<BR> return((sv&lt;0)?"-":"")+r;}<BR>function fC(n){<BR> for(var i=0;i&lt;4;++i){<BR> if(i!=n){m = frm.elements[Z[i]].value;v=1.0*m;<BR> if(v==0.0&#124&#124isNaN(v)){alert("You did not give a valid number for "+X[i]);return false;}<BR> V[i] = v;}<BR> }return true;}<BR>function pv(){if(!fC(0))return;<BR> rt=V[2]/tw;frm.PV.value=V[0]=fM(V[1]*fF(rt));fA();}<BR>function pmt(){if(!fC(1))return;<BR> rt=V[2]/tw;frm.PMT.value=V[1]=fM(V[0]/fF(rt));fA();}<BR>function per(){if(!fC(3))return;<BR> rt=V[2]/tw;var fc=1/(1-(V[0]*rt/V[1]));<BR> frm.PER.value=V[3]=fM(Math.log(fc)/(12*Math.log(1+rt)));fA();}<BR>function apr(){if(!fC(2))return;<BR> incr=(test=50.0/tw)/2;var pv;<BR> while(incr&#062;0.00004/tw){<BR> pv=V[1]*fF(test);<BR> if (pv&lt;V[0])test-=incr;else test+=incr;<BR> incr/=2.0;}<BR> if((test*=tw)&lt;0.01&#124&#124test&#062;99.9)frm. APR.value = "--invalid--";<BR> else{frm.APR.value=V[2]=fM(test);fA();}}<BR>&lt;/SCRIPT&#062;<BR>&lt;/HEAD&#062;<BR><BR>&lt;BODY onLoad="frm=document.money;"&#062;<BR>&lt;CENTER&# 062;<BR>&lt;H2&#062;Simple Loan Calculator&lt;/H2&#062;<BR>&lt;P&#062;<BR>Enter any three values and then push the &lt;b&#062;Calculate&lt;/b&#062;&lt;br&#062;<BR>button next to the fourth value to compute it. You can&lt;br&#062;<BR>see raw data and/or an amortization schedule for the loan&lt;br&#062;<BR>by checking the appropriate boxes at the bottom of the form.<BR>&lt;HR&#062;&lt;P&#062;<BR><BR>&lt;TABLE Border=5 CellPadding=20 BGColor=lightGreen&#062;<BR>&lt;TR&#062;&lt;TD&#06 2;<BR> &lt;FORM Name="money"&#062;<BR> &lt;TABLE Border=0 CellPadding=5&#062;<BR> &lt;TR&#062;<BR> &lt;TD align=right&#062;Loan amount:&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Name=PV Value=0.00 onChange="frm.PMT.focus();"&#062;&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Type=Button Value=Calculate onClick="pv();"&#062;&lt;/TD&#062;<BR> &lt;/TR&#062;&lt;TR&#062;<BR> &lt;TD align=right&#062;Payment amount:&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Name=PMT Value=0.00 onChange="frm.APR.focus();"&#062;&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Type=Button Value=Calculate onClick="pmt();"&#062;&lt;/TD&#062;<BR> &lt;/TR&#062;&lt;TR&#062;<BR> &lt;TD align=right&#062;Note rate:&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Name=APR Value=0.00 onChange="frm.PER.focus();"&#062;&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Type=Button Value=Calculate onClick="apr();"&#062;&lt;/TD&#062;<BR> &lt;/TR&#062;&lt;TR&#062;<BR> &lt;TD align=right&#062;Number of years:&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Name=PER Value=30 onChange="frm.PV.focus();"&#062;&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Type=Button Value=Calculate onClick="per();"&#062;&lt;/TD&#062;<BR> &lt;/TR&#062;&lt;TR&#062;<BR> &lt;TD colspan=3&#062;&nbsp;&lt;/TD&#062;<BR> &lt;/TR&#062;&lt;TR&#062;<BR> &lt;TD&#062;&lt;INPUT Type=CheckBox Name=RAW&#062;Do not round numbers.&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Type=CheckBox Name=AM&#062;Monthly amortization schedule.&lt;/TD&#062;<BR> &lt;TD&#062;&lt;INPUT Type=CheckBox Name=AY&#062;Annual amortization schedule.&lt;/TD&#062;<BR> &lt;/TR&#062;<BR> &lt;/TABLE&#062;<BR>&lt;/TD&#062;&lt;/TR&#062;<BR>&lt;/TABLE&#062;<BR>&lt;P&#062;<BR>&lt;FONT Size="-2"&#062;By Bill Wilkinson&lt;/FONT&#062;<BR>&lt;/CENTER&#062;<BR>&lt;/BODY&#062;<BR>&lt;/HTML&#062;<BR>

3. Senior Member
Join Date
Dec 1969
Posts
96,118

## I put it back online...

We had it online for 3 years but when we last reloaded the sites we left it out. Since it takes so little room, I restored it (and our other two entries into the contest).<BR><BR>http://www.juncojunction.com/5k/

4. Junior Member
Join Date
Dec 1969
Posts
3

## RE: I put it back online...

That&#039;s exactly what I was looking for, but you were right about interpreting it all. I would LOVE to see a bigger version. I&#039;ll do my best at running through it for now, but hopefully you can find one that uses real variable names. ;)

5. Senior Member
Join Date
Dec 1969
Posts
96,118

## Interpreting *part* of that...

The important part is the function fF.<BR><BR>That calculates the "factor" that is used in the pmt() [payment calculation], pv() [present value], and apr() [guess what] functions. (The per() [number of periods] uses completely different math, taking advantage of logarithms.)<BR><BR>As you can see, the function fF is:<BR><BR>function fF(i){return(1-Math.pow(1+i,-V[3]*12))/i;}<BR><BR>Which can be written more reasonably as:<BR> function factor( interestRate )<BR> {<BR> return (1 - Math.pow( 1 + interestRate, -numberOfPeriods ) ) / interestRate;<BR> }<BR><BR>In fF, I multiply V[3] by 12, but that because V[3] represents the number of *years*. And since the interestRate here is expressed as the *fraction* [not the %! Divide by 100] *per month* (that is, the APR/1200, if you prefer), we need to make the types of periods match that interest rate expression.<BR><BR>Then you can see how easy pmt() is to do:<BR><BR>function pmt()<BR>{<BR> if(!fC(1))return;<BR> rt=V[2]/tw; // tw is always 1200!<BR> frm.PMT.value=V[1]=fM(V[0]/fF(rt));<BR> fA();<BR>}<BR><BR>So rt is the monthly periodic interest rate (APR / 1200).<BR><BR>And basically, we are doing<BR> payment = presentValue / factor( APR/1200 )<BR><BR>(The fM function simply formats the value as money, for display purposes.)<BR><BR>And, of course, the pv() function similarly boils down to just<BR> presentValue = payment * factor( APR/1200 )<BR><BR>The per() function, to find the number of periods, is a bit weird. I&#039;ll let you work out the math (roughly trig level, though it doesn&#039;t use trig, per se).<BR><BR>function per(){if(!fC(3))return;<BR>rt=V[2]/tw;var fc=1/(1-(V[0]*rt/V[1]));<BR>frm.PER.value=V[3]=fM(Math.log(fc)/(12*Math.log(1+rt)));fA();}<BR><BR>That basically becomes:<BR><BR>function numberOfPeriods()<BR>{<BR> monthlyRate = APR/1200;<BR> var perFactor = 1 / ( 1 - ( presentValue * monthlyRate / payment ) );<BR> return Math.log(perFactor) / ( 12 * Math.log( 1 + monthlyRate );<BR>}<BR><BR>Quite frankly, I&#039;d have to sit down and work out the math of that from scratch, since it&#039;s been 4 years since I did it.<BR><BR>FINALLY...<BR><BR>The code to calculate the APR is as a I describe. An iteration that starts with an APR of 50% and an "increment" of 50%. And each time it adds or subtracts by half the prior increment. (That is, if 50% is too large, it subtracts 25% to get a result of 25%. If 25% is too large, it subtracts 12.5% to get 12.5%. If 12.5% is too small, it adds 6.25% to get 18.75%. If that&#039;s to large it subtracts 3.125%, etc., etc.)<BR><BR>See if you can work through the code I show there for the apr() function. If not, I could rewrite it in VBS. But consider it an exercise for the user.<BR><BR>

6. Senior Member
Join Date
Dec 1969
Posts
96,118

## Guess I should have said...

If you haven&#039;t seen the basic formula, it is simply:<BR><BR>PV = PMT * ( 1 - ( ( 1 + interestRate ) ^ -numberOfPeriods ) ) / interestRate )<BR><BR>or, even more mathematically,<BR><BR>[code language="VBScript"]<BR> -n<BR> ( 1 - ( 1 + i ) )<BR>V = P * ____________________<BR> i<BR>[/code]<BR><BR>Hopefully, you&#039;ve found that formula in your searching.<BR><BR><BR>

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•