This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using bisection search to determine
I have posted other thread but it did not receive answers thus i'm trying to provide some of my work to make more clear.
I need to use bisection method to determine monthly payment in order to pay off debt in one year exactly.
Here's some code:
originalBalance = 320000
annualInterestRate = 0.2
monthly_interest = annualInterestRate / 12
low = originalBalance/12
high = (originalBalance*(1 + monthly_interest)**12)/12
epsilon = 0.01
min_payment = (high + low)/2.0
while min_payment*12 - originalBalance >= epsilon:
for month in range(0, 12):
balance = (originalBalance - min_payment) * (1+monthly_interest)
if balance < 0:
low = min_payment
elif balance > 0:
high = min_payment
min_payment = (high + low)/2.0
print "lowest payment: " + str(balance)
However, I receive very way off answer: 298222.173851
My friend told me that correct answer is : 29157.09
Which is a lot lower than my...I guess the problem is in rounding(which I did not do yet) and preserving the balance after every looping and resetting it if balance is over 0. I cannot figure out how to attempt this problem and please, help someone :)
This is the correct one.
originalBalance = 320000
annualInterestRate = 0.2
monthly_interest = annualInterestRate / 12
low = originalBalance/12
high = (originalBalance*(1 + monthly_interest)**12)/12
epsilon = 0.01
min_payment = (high + low)/2.0
while min_payment*12 - originalBalance >= epsilon:
for month in range(0, 12):
balance = (originalBalance - min_payment)/10 * (1+monthly_interest)
if balance < 0:
low = min_payment
elif balance > 0:
high = min_payment
min_payment = (high + low)/2.0
print "lowest payment: " + str(balance)
This is what you need
while abs(x) > epsilon:
x = balance
for month in range(0, 12):
x = (x - ans) * (1+monthly_interest)
Related
I'm trying to create a program utilizing the Bisection Method (there are quite a lot of unused variables and confusing comments, so just ignore those). The value being outputted is fine, except it's getting stuck in an infinite loop and printing an infinite number of floating point digits. Isn't the epsilon supposed to stop this from happening? Here's my code:
total_cost = 1000000
downpayment = 0.25
amount_needed = total_cost * downpayment
annual_salary = int(input("Enter the starting salary: "))
monthly_salary = annual_salary / 12
num_of_months = 36
#needs changing
epsilon = .01
num_of_guesses = 0
low = 0
high = 100
ans = (high + low) / 2.0
ans = round(ans, 2)
#might need changing
while (num_of_months * (monthly_salary * (ans / 100)))**2 - amount_needed >= epsilon:
print("Low:", low, "High:", high, "Answer:", ans)
num_of_guesses = num_of_guesses + 1
if num_of_months * (monthly_salary * (ans / 100)) < amount_needed:
low = ans
elif num_of_months * (monthly_salary * (ans / 100)) > amount_needed:
high = ans
ans = (high + low) / 2.0
ans = round(ans, 2)
print("Number Of Guesses: ", num_of_guesses)
It's probably something really stupid but I honestly don't know what's going on XD
I'm trying to write a program that uses bisection to find a fixed monthly rate that will pay off a balance with a month. This is what I have at the moment and what I get is an infinite loop but I'm not sure why.
balance = 3329
tempB = balance
annualInterestRate = 0.2
monthlyIntrestRate = (annualInterestRate/12)
low = balance / 12
high = (balance * (1 + monthlyIntrestRate)**12)/12
avg = (high + low)/2
epsilon = 0.01
while abs(balance - epsilon) >= 0.01:
avg = (high + low)/2
for i in range(12):
monthlyUnpaidBalance = balance - avg
updatedBalanceMonth = monthlyUnpaidBalance + (monthlyIntrestRate * monthlyUnpaidBalance)
balance = updatedBalanceMonth
if abs(balance - epsilon) <= 0.01:
print(avg)
break
else:
balance = tempB
if abs(updatedBalanceMonth) > epsilon:
low = avg
elif abs(updatedBalanceMonth) < epsilon:
high = avg
I have a much simpler code that does the same thing but it is inefficient the code to it is
MinPay = 10
balance = 3329
tempB = balance
annualInterestRate = 0.2
monthlyIntrestRate = (annualInterestRate/12)
while balance >= 0:
for i in range(12):
monthlyUnpaidBalance = balance - MinPay
updatedBalanceMonth = monthlyUnpaidBalance + (monthlyIntrestRate * monthlyUnpaidBalance)
balance = updatedBalanceMonth
if balance <= 0:
print(MinPay)
break
else:
MinPay += 10
balance = tempB
In general, if you have infinite loop, I would suggest you run your code under pdb and do step trace to find why the loop doesn't end.
In your case, I think the issue is on these lines:
if abs(updatedBalanceMonth) > epsilon:
low = avg
elif abs(updatedBalanceMonth) < epsilon:
high = avg
which abs() should generally be greater than epsilon. I see your intention is that if your monthly pay is too much so the resulting balance is negative then you should set high to avg so you try with a lower pay on next search iteration. So you should remove abs() in these conditions.
But I would suggest you make your code easier to read as follows, especially that's intended for finance application:
balance = 3329
rate = 0.2 # 20% p.a.
lopay = 1
hipay = balance
epsilon = 0.01
monthly = 100 # search start
pv = sum([monthly/((1+rate/12)**i) for i in range(1,13)])
while abs(balance - pv) >= epsilon:
if pv > balance:
hipay = monthly
else:
lopay = monthly
monthly = (hipay + lopay) / 2
pv = sum([monthly/((1+rate/12)**i) for i in range(1,13)])
which you simply compute the present value of the 12 monthly payments and compare that to the starting balance.
It gets stuck an infinite loop because your expression:
abs(balance - episolon)
when it is evaluated in the while loop exit condition never actually changes.
If you get stuck in a while loop, you can try little modifications to code like this:
balance = 3329
tempB = balance
annualInterestRate = 0.2
monthlyIntrestRate = (annualInterestRate/12)
low = balance / 12
high = (balance * (1 + monthlyIntrestRate)**12)/12
avg = (high + low)/2
epsilon = 0.01
count = 1
while abs(balance - epsilon) >= 0.01 and count <= 100:
print(abs(balance - epsilon))
avg = (high + low)/2
for i in range(12):
monthlyUnpaidBalance = balance - avg
updatedBalanceMonth = monthlyUnpaidBalance + (monthlyIntrestRate * monthlyUnpaidBalance)
balance = updatedBalanceMonth
if abs(balance - epsilon) <= 0.01:
print(avg)
break
else:
balance = tempB
if abs(updatedBalanceMonth) > epsilon:
low = avg
elif abs(updatedBalanceMonth) < epsilon:
high = avg
count += 1
In this case, the iterations are capped and you can see the value that you are evaluating in your exit condition as:
3328.99
3328.99
3328.99
3328.99
3328.99
3328.99
3328.99
3328.99
3328.99
3328.99
(continuing)
Your going to need to refine your logic so that you can actually hit an exit condition.
The problem is from the MIT edX Python Course 6.00.1 Problem Set 1 Part C. Here are the problems. Scroll to part C. I'm aware that there are countless questions asked about the edX course but none of them have really helped me. Whenever I run my bisection search code, nothing happens. No error message, nothing. Could someone help me find the issue in my code? Sorry if code is horribly inefficient, very new to python and programming.
#Python script for finding optimal saving rate of monthly salary in order to purchase 1M house in 36 months
salary = float(input("Enter salary: "))
total_cost = 1000000
salary_raise = 0.07 #semiannual raise rate
down = 0.25 * total_cost #downpayment
steps = 0
r = 0.04 #annual investments returns
low = 0 #low parameter for bisection search
high = 10000 #high parameter
current_savings = 0
while (current_savings <= (down - 100)) or (current_savings >= (down + 100)):
current_savings = 0
monthly_salary = salary/12
guess_raw = (high + low)/2
guess = guess_raw/10000.0
months = 0
steps += 1
while months < 36: #Finds end amount of money after 36 months based on guess
months += 1
multiple = months%6
monthly_savings = monthly_salary * guess
current_savings = current_savings + monthly_savings + current_savings*r/12
if multiple == 0:
monthly_salary += salary_raise * monthly_salary
if (current_savings >= (down - 100)) and (current_savings <= (down + 100)): #If the guess is close enough, print the rate and number of steps taken
print ("Best savings rate: ",guess)
print ("Steps in bisection search: ",steps)
break
elif current_savings < (down - 100): #If the guess is low, set the low bound to the guess
if guess == 9999:
print ("It is not possible to pay the down payment in three years.")
break
else:
low = guess
elif current_savings > (down + 100): #If the guess is high, set the high bound to the guess
high = guess
First of all, I feel sorry. This is my first time to use this website so I don't know the rules.
I try to show my attempt but I don't know how to do this. I just rewrite the code directly day by day and don't have the saved drafts. I use many methods to work out, but I am fresh to coding and as you know, I keep on going the MIT CS introduction course.
For this problem, I would like to paste the original link but you need to sign in the website first. So I google it and find a Github page which contained the problem. enter link description here The problem set has three problems and I have solved first two of them.
It's about how to calculate credit cards latest monthly payment, and must use bisection search.
I have worked out once. However, I can only do one bisection search and then minus 0.01 step to step to approach the result. I show you my code before, here is the only old version which I saved.
balance = 999999
annualInterestRate = 0.18
monthly_interest_rate = annualInterestRate /12.0
lower_bound = balance / 12.0
upper_bound = (balance * (1 + monthly_interest_rate)**12) / 12.0
def calculate_balance(balance, fixed):
month = 0
while month < 12:
balance = (balance - fixed) * (monthly_interest_rate + 1)
month += 1
return balance
while True:
if calculate_balance(balance, lower_bound) > 0:
lower_bound = (lower_bound + upper_bound) / 2
else:
skipped_answer = lower_bound
break
#print(skipped_answer)
while True:
#print(balance, skipped_answer)
if calculate_balance(balance, skipped_answer) < 0:
skipped_answer -= 0.01
else:
break
print(round(skipped_answer+0.01, 2))
Anyway, this code works fine but the grader of edx says my code takes too much time.
So I think out of dual-directed bisection search and it takes me hours again. But this is the limit of my ability. I have no ideas. Here's the code below.
balance = 999999
annualInterestRate = 0.18
monthly_interest_rate = annualInterestRate /12.0
lower_bound = balance / 12.0
upper_bound = (balance * (1 + monthly_interest_rate)**12) / 12.0
def calculate_balance(balance, fixed):
month = 0
while month < 12:
balance = (balance - fixed) * (monthly_interest_rate + 1)
month += 1
balance
return balance
while True:
if abs(calculate_balance(balance, lower_bound) - balance) > 0.01:
if calculate_balance(balance, lower_bound) > 0:
mark = lower_bound
lower_bound = (lower_bound + upper_bound) / 2
elif calculate_balance(balance, lower_bound) < 0:
upper_bound = lower_bound
lower_bound = mark
else:
break
print(lower_bound)
I don't know why it will be an infinite loop. And how to solve it? What's wrong?
Thinking this for hours. I have tried all the methods that I know.
I worked out all of the exercises by myself and takes me too much time. This time, I know I must get help of experienced people. There must be something I don't know.
I don't knew is it now of any interest to see my code that works very fast. It is little
bit different then yours:
balance = 999999
annualInterestRate = 0.18
payment = 0
lower = balance/12.0
upper = (balance*(1+annualInterestRate/12)**12)/12.0
lbalance = 0
while payment < balance :
oldbalance = lbalance
lbalance = balance
payment = round((lower + upper)/2,3)
for i in range(0,12):
unpaidBalance = lbalance - payment
interest = unpaidBalance * annualInterestRate / 12.0
lbalance = unpaidBalance + interest
if round(lbalance,2) == 0 or oldbalance == lbalance:
print('Lowest Payment: ' + str(payment))
break
elif lbalance > 0 :
lower = payment
else:
upper = payment
Why both of your codes in some cases use bisection and in some don't? This is the main problem.
All the best to all of you
Have a nice day
I am creating a program that will compute the lowest monthly payment to be paid for a credit card, given a certain credit card balance and interest rate. The time frame for the payoff is 12 months and the monthly payment has to be accurate down to the nearest penny, using bisection search.
I was able to get the answer, the problem is that I couldn't get my while loop to quit once the monthly payment was calculated to the nearest cent, so I had to make an infinite while loop that has a elif statement at the bottom of the while loop that quits for me. I was wondering if anyone can figure out what condition to give the while loop so it will quit on its own. Also I just started learning python a week ago, and want some advice on how good/bad my code is. Any ideas?
# random balance
balance = 999999
# random interest rate
annualInterestRate = 0.18
# assign balance to another variable that will undergo the testing
balance_tested = balance
# bounds of bisection search
low = (balance / 12.0)
high = ((balance * (1 + (annualInterestRate/12.0))**12)/12.0)
# start month
month = 1
monthlyPayment = (low + high) / 2.0 #Averages out the bounds to meet in the middle
while abs(balance_tested != 0): #While loop that I can't get right, just made it to run infinitely
balance_tested = balance #Resets balance being tested back to original balance
monthlyPayment = (low + high) / 2.0 #Bisection search recalculates
month = 1 #Month reset back to 1
while month <= 12: #Loops through all 12 months with the payments being made and interested getting added
balance_tested = (balance_tested - monthlyPayment)
balance_tested += (balance_tested * (annualInterestRate/12))
month += 1
print "Balance Remaining: %.20f" % balance_tested
if balance_tested < 0: #If the bisection search guesses to high, decreases the high bound
high = monthlyPayment
elif balance_tested <= 0.01: #Conditional statement that stops the testing if the balance gets paid off to the cent
break
else: #If bisection search guesses to low, increases low bound
low = monthlyPayment
print "Monthly Payment: %.2f" % monthlyPayment
print "Lowest Payment: %.2f" % monthlyPayment
Is there any reason you're using the break statement instead of just putting that as the condition for your while loop?
balance = 999999
annualInterestRate = 0.18
balance_tested = balance
low = (balance / 12.0) #Lower bound of bisection search
high = ((balance * (1 + (annualInterestRate/12.0))**12)/12.0)
month = 1
monthlyPayment = (low + high) / 2.0
while not (balance_tested <= 0.01):
balance_tested = balance
monthlyPayment = (low + high) / 2.0
month = 1
while month <= 12:
balance_tested = (balance_tested - monthlyPayment)
balance_tested += (balance_tested * (annualInterestRate/12))
month += 1
print "Balance Remaining: %.20f" % balance_tested
if balance_tested < 0:
high = monthlyPayment
else:
low = monthlyPayment
print "Monthly Payment: %.2f" % monthlyPayment
print "Lowest Payment: %.2f" % monthlyPayment
You already have the condition, why not put that for the while statement instead?
while not balance_tested <= 0.01:
# etc.
while abs(balance_tested != 0):
will stay in the loop if the balance_tested becomes negative. Make this
while balance_tested >= 0.1:
This will automatically handle the rounding when it drops below a penny.