110-9.1

COMP 110Fall 2009

Readings: Snyder 18-21

Assignment 5: Due: 4:00 pm, Wednesday, October 28th, 2009

The Mortgage Calculator

"Neither a borrower nor a lender be" Polonius’ advice to Prince Hamlet's (3.1.78)

Introduction

“If I borrow X dollars for Y years at Z percent interest, what will my monthly payments be?”

When you take out a loan for a car or a house, you specify three parameters: the amount of the loan, the period of the loan, and the annual interest rate. From these three numbers, the monthly payment can be calculated. There are several ways to calculate the monthly payment. In this assignment you will do it by brute force using a simple mathematical technique calledbisection.

If you are trying to guess the answer to a math question and you have some way of knowing if your guess is too high or too low, then there’s an easy and efficient way to get the answer (or very close to it). You start by determining two extremes: one that is clearly too low (which we’ll call min) and one that is clearly too high (which we’ll call max). You then know that the right answer is trapped between minand max. You then guess at the midpoint between the extremes: mid = (min + max)/2. If this is too high, then you know the correct answer must lie in the range min…mid. If your guess is too low, then you know the answer is in the range mid…max. We’ve now cut the possible range in half. We continue this way successively halving the possible range until we get close enough.

For example, on the quiz show The Price is Right, you are asked to guess the price of a fabulous prize: a big screen television. You make a guess and then Drew Carey tells you if your guess is too high or too low. You start with min of 0 (the prize clearly costs more than nothing) and a max of, say, $10,000 – clearly more than the TV is worth. Your first guess is (min+max)/2 or $5000. Drew says that’s too high, so now you know that the price is between 0 and $5000. So your next guess is (0+5000)/2 or $2500. Drew says that is too low. So now you know the price is in $2500…$5000. Your next guess is (2500+5000)/2 or $3750. You continue this way until you get the correct price. Because you are halving the size of the possible range at each step, you arrive at the correct price very quickly. For example, starting with min of $0 and max of $10,000, you can get the correct price (within one dollar) in fourteen guesses or fewer[1].

Determining monthly payment

If you borrow $10,000 at 6% annual interest, here’s how the process goes. First, we have to convert annual interest to monthly fraction by dividing by 1200. (You are dividing annual percentage by 100 to get the annual fraction and then by 12 to get the monthly fraction.) So for 6% annual interest, the monthly rate is 0.5%; the monthly fraction is 0.005. Then each month, the balance you owe is increased because of the interest and decreased by your payment.

new balance = old_balance + old_balance*monthly_int_fraction – payment;

The perfect monthly payment is the one that will reduce your balance to zero (or, in this case, within a penny of zero) after the specified number of payments.

Determining the initial min and max

If you borrow $10,000 for 10 years at 6% interest, your monthly payment is clearly more than $0 and clearly less than $10,000. So these will be our starting points. Our first guess will be (0+10000)/2 or $5000. Paying $5000 per month for 10 years will result in a negative balance (we paid too much), so our next guess will be (0+5000)/2 or $2500. This is also too big. The process continues until we discover, after about 28 steps that $111.02 is the perfect monthly payment. The perfect monthly payment is the one that has a final balance (the amount left to pay after the final payment) between $0.00 and $0.01 (that is, between zero and one cent). The loan will cost us a total of $111.02*120 = $13,322.40 (the monthly payment multiplied times the number of months.)

Program

Your job is to build a monthly payment calculator. The user will enter a loan amount, a period (in years) and a rate (as a percent, possibly with fractional part), press a button, and the calculator will display the monthly payment, the total amount paid, the number of steps required to reach the solution, and the amount of time required to make the calculation.

Your page should contain the following:

A few lines of instructions

Appropriately labeled text boxes for the loan amount, loan period, and rate.

A “Calculate” button

Text areas for the perfect monthly payment, the total paid, the number

of steps required, and time required (in seconds).

A “Reset” button that clears the form.

Your page need not look exactly like the one shown below, but should contain all the information shown.

Errors checked for

Your program should detect and handle the following errors. An alert message is sufficient. It’s also nice to clear the offending field (but not the other fields).

1. A loan amount that is zero or less (no one borrows zero).

2. A loan amount that is not a number[2] (e.g. “Hello”).

2. A loan period that is not an integer[3], is less than one, or not a number.

3. A rate that is less than zero or not a number.

What to turn in

Save your html file under your onyen in the public_html folder with an 8-character secret name. Don’t link it to anything. Put the name of the file as a comment in the html. Turn in a paper copy of your program. Also, attach a set of test data that you used to test your program. The best format for this is a table (easy if you use Excel or Word) with four columns. Each row represents one test; each column contains the three input values and the result.

Etc.

You should display both the perfect monthly payment and the total paid with two decimal places (see monthly payment above). You can easily round a value to 2 decimal places by multiplying by 100, rounding using Math.round, then dividing by 100. If the ones digit happens to be zero, you will get one decimal place rather than 2 (see total payment above). Don’t worry about this.

Keeping track of time

Keeping track of running time is pretty easy. You first determine the starting time by creating a Date object and getting the time.

var d_start = new Date();

var t_start=d_start.getTime();

This will set t_start to the number of milliseconds (thousandths of a second) since January 1st, 1970. When computation is complete, you do the same:

var d_stop=new Date();

var t_stop=d_stop.getTime();

Then the expression

t_stop – t_start

tells you how many milliseconds were required. Then you convert that to seconds by dividing by 1000.

Extra challenge (for a little extra credit)

An alternative way to solve this problem, but far less efficient, is to try all values starting at 1¢ and increase by a penny until the ideal value is found. Try it and see how the times compare with bisection. You'll find that this method is pretty good for small loan amounts, but disastrously slow for large loans.

[1] For the mathematically minded, you can guess a number between 0 and N in log2(N) guesses (or fewer if you’re lucky).

[2] The built-in function isNaN(x) is true if x is not a number. Sort of backwards, but that’s what’s available. Note that the empty string is interpreted as the number 0, so isNaN(“”) is false.

[3] To determine if a number is an integer, take its floor (Math.floor) and see if it equal to the original. For example Math.floor(4) and Math.floor(4.5) are both 4. So Math.floor(4)==4 is true while Math.floor(4.5)==4.5 is false. Good exam question: write a function isAnInteger(x) that returns true if x is an integer and false otherwise (hint: requires one line).