My code passes test cases but if anything about ~949,000 is input it enters an infinite loop.
I need to calculate the best rate at which to save a portion of a monthly income to save in order to afford a down payment in 36 months with 2 significant digits. I'm thinking this has something to do with me not quite understanding how epsilon is calculated - I've tried calculating epsilon as 0.0001 * total_cost, 0.0004 * portion_down_payment, and 0.0001 * annual_income all to no avail.
#House Hunting ps1c
low = int(0)
high = int(10000)
percent_saved = (low + high)/2.0
current_savings = 0
annual_salary = int(input("What is your starting anual salary? "))
total_cost = 1000000
semi_annual_raise = 0.07
portion_down_payment = total_cost * 0.25
epsilon = 100
r = 0.04
total_months = 0
steps = 0
while True:
current_savings = 0
monthly_salary = annual_salary/12
for i in range(1,37):
current_savings += (current_savings*r/12)
current_savings += (monthly_salary * (percent_saved / 10000))
total_months += 1
if total_months % 6 == 0:
monthly_salary += monthly_salary * semi_annual_raise
steps +=1
if abs(current_savings - portion_down_payment) <= epsilon:
print("Steps in bisectional search: ", steps)
best_savings_rate = str(percent_saved / 100)
print("Best savings rate: ", (best_savings_rate + "%"))
break
elif (portion_down_payment - 100) - current_savings > 0:
low = percent_saved
percent_saved = int((low + high) / 2.0)
else:
high = percent_saved
percent_saved = int((low + high) / 2.0)
if percent_saved >= 9999:
print("It is not possible to afford this in 3 years")
break
Test Case 1
Enter the starting salary: 150000
Best savings rate: 0.4411
Steps in bisection search: 12
Test Case 2
Enter the starting salary: 300000
Best savings rate: 0.2206
Steps in bisection search: 9
Test Case 3
Enter the starting salary: 10000
It is not possible to pay the down payment in three years
My code passes all test cases but when the input is too high it enters an infinite loop that I don't know how to reconcile.
Essentially when annual salary becomes higher the optimal savings rates becomes smaller. When the optimal savings rate becomes smaller then the level of precision you require for
abs(current_savings - portion_down_payment) <= epsilon
becomes higher.
When you cast percent_saved to an int in
percent_saved = int((low + high) / 2.0)
it artificially limits the precision and then code enters an infinite loop.
Remove the cast and the code will work always.
Related
Link to pset 1(https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/assignments/MIT6_0001F16_ps1.pdf)
Hello,
I've been working through the bisectional search problem for the MIT 6.0001 course's pset1. I feel like I have all components down, but it keeps giving me the same answer for savings rate and steps in bisectional search no matter what input I give. Could anyone tell me what I have done wrong here?
# User input
annual_salary = float(input('Enter the starting salary: ' ))
# Given sets of assumption
total_cost = 1000000
semi_annual_raise = 0.07
portion_down_payment = 0.25
current_savings = 0
r = 0.04 # Annual investment interest rate of current savings
down_payment = portion_down_payment * total_cost
num_guess = 0 # Bisectional search guess count starts at 0
# Lowest and highest integer savings rate in intial bisection search
low = 0
high = 10000
guess = (high + low)//2.0
while abs(down_payment - current_savings) >= 100:
current_savings = 0
rate = guess/10000
for month in range(36):
if month%6 == 0 and month > 0:
annual_salary += annual_salary * semi_annual_raise
monthly_salary = annual_salary/12
current_savings += (rate * monthly_salary) + current_savings*(r/12)
# Bisectional search introduced
if current_savings < down_payment:
low = guess
else:
high = guess
guess = (high + low)//2.0
num_guess += 1
if num_guess > 13:
break
print('Best savings rate:', rate)
print('Steps in bisection search:', num_guess)
You should reset the annual_salary variable to its original value (value from the input) each time before going through the [for loop] because each iteration tries a different saving rate guessing with the same starting salary.
I suggest you use a different variable (e.g. updated_annual_salary) and assign the starting salary to it to be able to reset it over and over.
Another thing is that when the annual salary gets updated, the monthly salary gets updated too and so does the saved portion. So, your [while loop] should start like this:
while abs(down_payment - current_savings) >= 100:
updated_annual_salary = annual_salary
current_savings = 0
rate = guess / 10000
for month in range(36):
if month % 6 == 0 and month > 0:
updated_annual_salary += updated_annual_salary * semi_annual_raise
monthly_salary = updated_annual_salary / 12
current_savings += (rate * monthly_salary) + current_savings * (r / 12)
annual_salary = int(input("Your annual salary "))
semi_annual_raise = 0.07
r = 0.04
down_payment = 250000
epsilon = 100
low = 0
high = 10000
guess = (high + low)//2
best_saving_rate = (guess/10000)
months = 0
current_savings = 0
steps = 0
while abs(current_savings - down_payment) >= 100:
for i in range(36):
current_savings += best_saving_rate*(annual_salary/12) + (current_savings*r)/12
months +=1
if months%6 == 0:
annual_salary = annual_salary + semi_annual_raise*annual_salary
if current_savings < down_payment:
low = guess
else:
high = guess
steps += 1
guess = (high + low)//2
best_saving_rate = float(guess/10000)
print(steps)
print(best_saving_rate)
print(current_savings)
This code is supposed to find the best saving rate for someone who is trying to have enough money for a payment of 250000 dollars in 36 months. I use bisection search and I think I'm in the right track but it won't work. I think the problem is that the variable current savings is not reinitializing with every iteration and I do not know how to make it do that. PLEASE HELP.
Why are you expecting the current_savings to be reset to 0 with every iteration? You do not do that in the code, so what would cause that to happen? Also by the looks of the code, you should be resetting months to 0 as well (though it appears that the for loop index variable i should actually be the month).
This fixes the obvious errors that I could see:
while abs(current_savings - down_payment) >= 100:
current_savings = 0 # add this
for month in range(36): # Change this
current_savings += best_saving_rate * (annual_salary / 12) + (current_savings * r) / 12
# months += 1 <-- remove this
if months % 6 == 0:
PSet_1a - Baseline
This prompts the user for the cost of their dream house, their salary, the portion of their monthly salary that they are willing to save, and returns the number of months it would take for them to have a down payment (25% of the cost of their dream house)
total_cost = float(input('How much is the dream house? '))
portion_down_payment = 0.25
current_savings = 0
r = 0.04
annual_salary = float(input('What is your salary? '))
portion_saved = float(input('What is the amount saved per month? '))
monthly_salary = annual_salary / 12.0
amount_down_payment = total_cost * portion_down_payment
portion_amount = monthly_salary * portion_saved
months = 0
while current_savings <= amount_down_payment:
current_savings += portion_amount + (current_savings * (r / 12))
months += 1
print(current_savings, months)
PSet_1b - Adjusted for Semi-Annual Raise
Prompts the user as the same above but this one asks for a semi annual rate, turns it into a number to add to the annual raise.
total_cost = float(input('How much is the dream house? '))
portion_down_payment = 0.25
current_savings = 0
r = 0.04
annual_salary = float(input('What is your salary? '))
portion_saved = float(input('What is the amount saved per month? '))
semi_annual_rate = float(input('What is the rate of your semi-annual_raise? '))
monthly_salary = annual_salary / 12.0
semi_annual_raise = monthly_salary * semi_annual_rate
amount_down_payment = total_cost * portion_down_payment
portion_amount = monthly_salary * portion_saved
months = 0
while current_savings <= amount_down_payment:
months += 1
if months % 6 == 0:
annual_salary += semi_annual_raise
current_savings += portion_amount + (current_savings * (r / 12))
print(current_savings, months)
Both programs return the same results when I run them and I have been trying to figure out why and how on my own for a few hours now without much improvement.
The answer is to update portion_amount per 6 months through if statement and not to go through it semi_annual_raise on the annual_salary.
Thanks to Randy from the comments.
Forewarning, I have just started learning python so please bear with me on my beginner code.
So in the MIT6_0001 course on python. You are given a problem where you are supposed to find the "optimal monthly saving rate" for a 25% downpayment on a 1 million dollar house in a 36 month time period using a bisection search algorithm, where you're starting salary is 150,000 and a semi-annual raise of 7%. You must also account for an annual ROI 4% on your savings.
I have been working on this for a week. at first, I tried it without the for loop and that pretty much returned best savings rate as 100% which is where my main problem lies, I can't get around the fact that each time I bisect the value it will always be low so it just keeps trying to get closer and closer to 1 until the epsilon value is reached in the while loop. I have seriously been losing sleep over this please help
total_cost = 1000000
annual_salary =150000
current_savings = 0
epsilon = 100
low = 0
high = 10000
savings_rate= (low + high)/2
down_payment = .25 * total_cost
raise_rate = .07
month_count = 0
r = .04/12
step_count = 0
while current_savings-down_payment <= epsilon :
for i in range(36):
if month_count != 0 and month_count % 6 == 0:
annual_salary += annual_salary * raise_rate
current_savings += current_savings * r + (annual_salary/12) * (savings_rate/10000)
if current_savings < down_payment:
low = savings_rate
print("low =",low)
else:
high = savings_rate
print("high =",high)
month_count += 1
savings_rate= (low + high)/2
step_count += 1
print("Best savings rate: ",savings_rate/10000)
print("Steps in bisection sear: ",step_count)
expected output
Best savings rate: 0.4411
Steps in bisection search: 12
actual
Best savings rate: 0.5
Steps in bisection search: 1
Remember our goal is to take a continuous function and find the approximate points where it is zero in our graph. Our function in this case is abs(current_savings-down_payment)-epsilon = 0.I think the problem your having is that the absolute value of current savings minus down payment has to be less than epsilon and you are testing whether it is greater than epsilon instead.
I figured out the solution.
total_cost = 1000000
annual_salary = 150000
current_savings = 0
epsilon = 100
low = 0
high = 10000
down_payment = .25 * total_cost
raise_rate = .07
r = .04/12
step_count = 0
while abs(current_savings - down_payment) >= epsilon:
savings_rate = float(low + high) / 2.0 #take care of integer division
current_savings = 0 # reset for next itteration
annual_salary = 150000 #reset for next itteration
# print("savings_rate = %f " % (savings_rate/10000)) #4debugging
# print("current_savings= ", current_savings) #4debugging
for i in range(1,36): #initiate range at 1, easier to handle 6 month raise
if i != 1 and i % 6 == 0:
annual_salary += annual_salary * raise_rate
current_savings += current_savings * r + (annual_salary/12) * (savings_rate/10000)
# print("count =",i) #4debugging
# print("annual_salary: ", annual_salary) #4debugging
print ("current_savings=%f, down_payment=%f" % (current_savings, down_payment) )
print ("diff = %f " % abs(current_savings - down_payment) )
if (step_count > 20):
print('**********ERROR**********: inf loop')
break # exit infinite loop
elif current_savings < down_payment:
low = savings_rate #update range low if less than down payment
print("new range: %f -> %f" % (low, high) )
elif current_savings > down_payment:
high = savings_rate #update range high if greater than down payment
print("new range: %f -> %f" % (low, high) )
print("")
step_count += 1
print ("current_savings=%f, down_payment=%f" % (current_savings, down_payment) )
print ("diff = %f " % abs(current_savings - down_payment) )
print("best savings rate: ",savings_rate/10000)
print("number of bisection steps: ",step_count)
I've been going nuts about this problem for hours, and I've been redoing it over and over! At this point I think I'm actually seeing numbers flying around me.
Anyway, I'm supposed to write a program that finds the correct amount of money to pay each month over one year, to pay off debt on a credit card. So with this program, there's a few conditions that must be met.
It must be done by using bisection search ((low + high) / 2)
There's a set balance
There's an annual interest rate.
Here's my code at the moment, and all I'm getting with this is infinite loops. What am I doing wrong here?
balance = 320000
annualInterestRate = 0.2
monthly_interest = float(annualInterestRate) / 12.0
lower_bound = float(balance / 12)
upper_bound = (balance * (1 + monthly_interest)**12) / 12.0
epsilon = 0.01
ans = float(lower_bound + upper_bound) / 2
while abs((balance * (1 + monthly_interest)**12) / 12.0) >= epsilon:
ans = float(lower_bound + upper_bound) / 2
total = float(ans * 12)
new_balance = 0
interest = 0
for month in range(0, 12):
interest += ans + (1 + monthly_interest)
new_balance += ans + interest
if new_balance > balance:
upper_bound = ans
print "low" + str(new_balance)
elif new_balance < balance:
lower_bound = ans
print "high" + str(new_balance)
else:
print "What's going on here?"
print "Lowest payment: %r" % ans
I believe there are a couple things wrong here, so first things first, your while is an infinite loop because the condition you are using will never converge to a solution (the variable values never change inside the loop). On top of that the condition (of the while) seems wrong for this kind of problem.
This is what I think you are trying to do, you are trying to find the upper and lower bounds for "the monthly payment" and the convergence condition for that is that the difference between those bounds should be less to a constant epsilon (in other words the error should be less than epsilon).
inside your loop you are calculating the midpoint correctly, this midpoint already is taking into account the interest but are calculating it again. The conditions to change the upper and lower bound are not taking into account the interest so this part of the code is a little messy.
So, modifying those conditions your program actually converges to a solution:
balance = 320000
annualInterestRate = 0.2
monthly_interest = float(annualInterestRate) / 12.0
lower_bound = float(balance / 12)
upper_bound = (balance * (2 + monthly_interest)**12) / 12.0
epsilon = 0.001
ans = float(lower_bound + upper_bound) / 2
total_debt=balance * (1 + annualInterestRate)
print total_debt
while (upper_bound - lower_bound) >= epsilon:
ans = float(lower_bound + upper_bound) / 2
total = float(ans * 12)
if total > total_debt:
upper_bound = ans
print "low " + str(total)
elif total < total_debt:
lower_bound = ans
print "high " + str(total)
else:
print "Solution found"
break
print "Lowest payment: %r" % ans
Hope it helps!