LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Python Help (http://www.linuxquestions.org/questions/programming-9/python-help-4175451529/)

joshp 02-24-2013 04:14 PM

Python Help
 
Hey All,
I am working on a MITx class and having problems with the following, I am supposed to use bisection search to find the min payment of the given balance over the course of year for it to be 0. Been working on this the last twoish days and have not gotten stuck.

Code:

balance = 320000
annualInterestRate = 0.2


monInterest=annualInterestRate/12
originalBalance=balance
low=originalBalance/12
epsilon = 0.01
high = (originalBalance*(1 + monInterest)**12)/12
min_payment = (high+low)/2
total_interest=0

print "Before While: " + str(min_payment*12 - (originalBalance + total_interest) )

while min_payment*12 - (originalBalance + total_interest)  >= 0: 
   
    print "Total Inter: "+ str(total_interest)
    print "Min Paymen: " + str(min_payment)
   
    for month in range(0, 11):
       
        balance = balance - min_payment * ( monInterest)
        print "Bal in For: " + str(balance)
        total_interest += (balance * monInterest)
        #print total_interest
   
   
    print "Bal " + str(balance)
    if balance  < 0:
        low = min_payment
     
    elif balance > 0:
        high = min_payment
        min_payment=(high + low)/2.0
 
   
print "Lowest Payment: " + str(round(balance,2))

Its outputting that the Lowest Payment is 314574.88. From the answer I see on the site it should be 29157.09. I have a feeling I am missing something obivios here. Any one have any ideas?

Josh

ntubski 02-24-2013 09:49 PM

There are a lot of errors in your program, I noted them in red:

Code:

balance = 320000
annualInterestRate = 0.2 # not an error, but 20% interest rate, yikes!


monInterest=annualInterestRate/12
originalBalance=balance
low=originalBalance/12
epsilon = 0.01 # your epsilon is too big
high = (originalBalance*(1 + monInterest)**12)/12
min_payment = (high+low)/2
total_interest=0

print "Before While: " + str(min_payment*12 - (originalBalance + total_interest) )

# should be using epsilon here
while min_payment*12 - (originalBalance + total_interest)  >= 0: 
   
    print "Total Inter: "+ str(total_interest)
    print "Min Paymen: " + str(min_payment)
   

    # you need to reset balance and total_interest here
    for month in range(0, 11): # a year has 12 months
       
        balance = balance - min_payment * ( monInterest) # interest doesn't apply to the payment
        print "Bal in For: " + str(balance)
        total_interest += (balance * monInterest)
        # you need to compound your interest
        #print total_interest
   
   
    print "Bal " + str(balance)
    # you have your bisectioning backwards
    if balance  < 0:
        low = min_payment
     
    elif balance > 0:
        high = min_payment
        min_payment=(high + low)/2.0 # this should not be exclusive to the left bisection
 

# you printed the wrong variable here   
print "Lowest Payment: " + str(round(balance,2))


psionl0 02-25-2013 03:14 AM

Code:

# should be using epsilon here
while min_payment*12 - (originalBalance + total_interest)  >= 0:

You should also use an absolute value function.


Code:

    for month in range(0, 11): # a year has 12 months
       
        balance = balance - min_payment * ( monInterest) # interest doesn't apply to the payment

Counting from 0 to 11 gives 12 months so that is not the problem.

The correct formula for calculating the balance is:
balance = balance * (1 + monInterest) - min_payment

psionl0 02-25-2013 06:12 AM

@joshp, I fixed up your code (there are errors in your code that haven't been listed yet) and the correct answer is $29,643.04. The $29,057.09 that you see on the site is the amount owing at the beginning of the 12th month but interest still has to be added for that month too.

I verified my answer using a spreadsheet program and this is what the spreadsheet displays:
Code:

month            start            interest      pay        end
  1    320000            5333.3333333333 29643.0415 295690.291833333
  2    295690.291833333  4928.1715305556 29643.0415 270975.421863889
  3    270975.421863889  4516.2570310648 29643.0415 245848.637394954
  4    245848.637394954  4097.4772899159 29643.0415 220303.07318487
  5    220303.07318487  3671.7178864145 29643.0415 194331.749571284
  6    194331.749571284  3238.8624928547 29643.0415 167927.570564139
  7    167927.570564139  2798.7928427357 29643.0415 141083.321906875
  8    141083.321906875  2351.3886984479 29643.0415 113791.669105322
  9    113791.66910532  1896.5278184221 29643.0415  86045.1554237445
 10    86045.1554237445  1434.0859237291 29643.0415  57836.1998474736
 11    57836.1998474736  963.9366641246 29643.0415  29157.0950115982
 12    29157.0950115982  485.9515835266 29643.0415      0.0050951248
                               
                        35716.5030951247

If you can't get your code working properly, PM me and I will send you my listing. (It's actually written in blassic but the syntax is similar to python).

audriusk 02-25-2013 06:35 AM

Quote:

Originally Posted by psionl0 (Post 4899103)
Code:

    for month in range(0, 11): # a year has 12 months
       
        balance = balance - min_payment * ( monInterest) # interest doesn't apply to the payment

Counting from 0 to 11 gives 12 months so that is not the problem.

The end point is omitted in range() results, so it is a problem.

psionl0 02-25-2013 07:43 AM

Quote:

Originally Posted by audriusk (Post 4899202)
The end point is omitted in range() results, so it is a problem.

Sounds like a gotcha to me. That's why I prefer the for syntax used in C.

audriusk 02-25-2013 08:36 AM

Not really a gotcha, unless one is new to Python. It's documented (see help(range) in Python's interactive mode or pydoc range in the shell) and consistent to how list slicing works: foo[n:m] will return list elements from n (inclusive) to m (exclusive).

ntubski 02-25-2013 10:06 AM

Quote:

Originally Posted by psionl0
Code:

# should be using epsilon here
while min_payment*12 - (originalBalance + total_interest)  >= 0:

You should also use an absolute value function.

Yes, I was trying to leave a bit of thought for the OP to do.

Quote:

Code:

    for month in range(0, 11): # a year has 12 months
Counting from 0 to 11 gives 12 months so that is not the problem.
As audriusk mentioned, python's range is right-open, so range(0, 11) means [0, 11).
Quote:

Sounds like a gotcha to me. That's why I prefer the for syntax used in C.
It would be even more of a gotcha if you had to do range(0, len(list)-1) to get the indexes of a list. Also note that range(12) is the same as range(0, 12).

Quote:

The correct formula for calculating the balance is:
balance = balance * (1 + monInterest) - min_payment
...
the correct answer is $29,643.04. The $29,057.09 that you see on the site is the amount owing at the beginning of the 12th month but interest still has to be added for that month too.
$29,643.04 is the answer if you make payments at the end of the month, $29,157.09 if you make them at the beginning.

Quote:

If you can't get your code working properly, PM me and I will send you my listing. (It's actually written in blassic but the syntax is similar to python).
They won't be able to use PMs until 150 posts. I would also ask you to refrain from handing out answers.

psionl0 02-25-2013 05:31 PM

Quote:

Originally Posted by ntubski (Post 4899345)
$29,643.04 is the answer if you make payments at the end of the month, $29,157.09 if you make them at the beginning.

If the payments are made at the beginning of the month then my formula for the balance is incorrect. Also, the loan would effectively be paid off in 11 months instead of 12 so the exit condition of the outer loop as written in the OP is also incorrect (of course there was a much simpler test that could have been used).

Quote:

Originally Posted by ntubski (Post 4899345)
They won't be able to use PMs until 150 posts.

I was unaware of that. It seems unnecessarily restrictive to me.

Quote:

Originally Posted by ntubski (Post 4899345)
I would also ask you to refrain from handing out answers.

In my experience (I have been a private tutor for many years), it will never happen. ;)

mina86 02-25-2013 08:06 PM

Quote:

Originally Posted by psionl0 (Post 4899244)
Sounds like a gotcha to me. That's why I prefer the for syntax used in C.

It's actually pretty much like the syntax in C if you are used to using less-than. range(x, y) maps to for (i = x; i < y; ++i) and range(x, y, z) maps to for (i = x; i < y; i += z).

ntubski 02-25-2013 08:12 PM

Quote:

Originally Posted by psionl0 (Post 4899627)
If the payments are made at the beginning of the month then my formula for the balance is incorrect. Also, the loan would effectively be paid off in 11 months instead of 12 so the exit condition of the outer loop as written in the OP is also incorrect (of course there was a much simpler test that could have been used).

The time between the first and last payments is 11 months in both cases, but there are 12 payments in both cases so the outer loop test is still correct (except for the abs() and epsilon thing).

psionl0 02-25-2013 09:52 PM

Quote:

Originally Posted by ntubski (Post 4899719)
The time between the first and last payments is 11 months in both cases, but there are 12 payments in both cases so the outer loop test is still correct (except for the abs() and epsilon thing).

The outer loop test does not give the balance as you would expect because total_interest is not calculated correctly.


All times are GMT -5. The time now is 02:14 PM.