What's different between lines 16 and 17?
#user input
annual_salary = float(input("Enter your annual salary: "))
portion_saved = float(input("Enter the percent of your salary to save, as a decimal: "))
total_cost = float(input("Enter the cost of your dream home: "))
#static vars
portion_down_payment = total_cost*.25
monthly_salary = annual_salary/12
r = .04 #annual rate of return
months_to_save = 0
current_savings = 0
investment_return = current_savings * r / 12
while current_savings < portion_down_payment:
#current_savings += (current_savings * r / 12) + (portion_saved * monthly_salary) # Line 16
current_savings += (investment_return) + (portion_saved*monthly_salary) # Line 17
months_to_save += 1
print("Number of months: ", months_to_save)
I tried running it through pythontutor and the variation happens on step 15 of execution, but I can't quite figure out what's different.
When you use current_savings += investment_return, it adds the same amount of interest to current_savings each time through the loop. That interest is equal to current_savings * r / 12 calculated before you started the loop.
But when you use current_savings += (current_savings * r / 12), you recalculate the interest each time through the loop. So the interest is calculated based on the current value of current_savings, which gets bigger each time the loop runs.
In other words, the first one calculates simple interest, and the second one calculates compound interest.
I need to use bisection search to approximate the square root of a number. I wrote the following code but it only works when my number is greater than 1. If it's a decimal like 0.36 in the following example, my code is just not working. Could you please look at it and give me suggestions on why and how to fix it?
x = 0.36
dp = 0.01
numGuesses = 0
low = 0.0
high = x
ans = (high + low)/2.0
while abs(ans**2 - x) >= dp:
print("low ="+ str(low) + "high = " + str(high) + " ans = " + str(ans))
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print("numGuesses =" + str(numGuesses))
print(str(ans) + "is close to square root of" + str(x))
If the number is less than 0 then the root of that number will be greater than that. So you should start from 1. Try this
x = 0.36
dp = 0.01
numGuesses = 0
low = 0.0
high = x
ans = 0
if x> 1:
ans = (high + low)/2.0
else:
ans = 1
while abs(ans**2 - x) >= dp:
print("low ="+ str(low) + "high = " + str(high) + " ans = " + str(ans))
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print("numGuesses =" + str(numGuesses))
print(str(ans) + "is close to square root of" + str(x))
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
So I'm entirely new to coding and I'm taking the MIT Openwarecourse to get started (and I'm using the book Introducing to Computation and Programming using Python)
Also since I'm new here I'm a bit afraid that my question is low quality so please point out if you think I should improve the manner on how I asks questions.
At 3.4 I'm given the code:
x = int(input("Please enter an integer: "))
epsilon = 0.01
numGuesses = 0
low = -100
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 -x) >= epsilon:
print ("low = ", low, "High=", high, "ans=", ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print ("numGuesses =", numGuesses)
print (ans, "Is close to square root of", x)
So what I tried to do first is understand each line of the code and what it exactly does. I've been given the hint: "Think about changing low to ensure that the answer lies within the region being searched.)
I've tried to change low to a negative number and I tried to add if low is less than 0, then low = -low like this:
x = int(input("Please enter an integer: "))
epsilon = 0.01
numGuesses = 0
low = 0.0
if low < 0:
low = -low
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 -x) >= epsilon:
print ("low = ", low, "High=", high, "ans=", ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print ("numGuesses =", numGuesses)
print (ans, "Is close to square root of", x)
However I'm probably taking a wrong approach...
You were very close, to convert the program to find an approximation to the cube root of both negative and positive numbers you have to only change the range in which your algorithm is searching.
To find cube root of positive numbers:
x = 8
epsilon = 0.01
numGuesses = 0
high = max(1.0, x)
low = 0.0
ans = (high + low) / 2.0
while abs((pow(ans,3)- x)) >= epsilon:
print("low ",low," ,high ",high," ans ",ans)
numGuesses += 1
if pow(ans,3) < x:
low = ans
else:
high = ans
ans = (high + low) /2.0
print("numguesses , = "+str(numGuesses))
print(str(ans)+"is close to square root of x "+ str(x))
The algorithm searches between low and high.
Suppose a user enters a number say 8 implies high = 8 and low = 0.0 and then it performs the search and will output 2.0, if user enters a negative number say -8 then high = 1.0 and low = 0.0 which don't appear to be right,the correct limit should be i.e [-8,0) (cube root of a negative number is negative) "ignoring complex roots", in this case high = 0 and low = -8.
You can do it by a simple if else statement.
x = 8
epsilon = 0.01
numGuesses = 0
high = max(1.0, x)
low = 0.0
if x < 0:
low = x
else:
None
ans = (high + low) / 2.0
while abs((pow(ans,3)- x)) >= epsilon:
print("low ",low," ,high ",high," ans ",ans)
numGuesses += 1
if pow(ans,3) < x:
low = ans
else:
high = ans
ans = (high + low) /2.0
print("numguesses , = "+str(numGuesses))
print(str(ans)+"is close to square root of x "+ str(x))
I hope this is a beginner friendly answer.
To solve the problem I used the min function and compared x to 1.0, then extracted the lowest value. I did this because it is the direct inverse of extracting the initial high value.
x = -25
epsilon = 0.01
num_guesses = 0
low = min(x, 1.0)
high = max(1.0, x)
ans = (high + low) / 2.0
while abs(ans**3 - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
num_guesses += 1
if ans**3 < x:
low = ans
else:
high = ans
ans = (high + low) / 2.0
print('num guesses =', num_guesses)
print(ans, 'is close to cube root of', x)
I wrote an alternative code that allows negatives of square, cube, etc roots while keeping the core of OP's code unchanged:
number = int(input('Number? '))
x = abs(number)
root = int(input('Root? '))
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**root - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**root < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
if number < 0:
if root%2 == 1:
ans = -ans
else:
ans = str(ans)+'i'
print(ans, 'is close to square root of', number)
It takes the input number as absolute and checks its signal after the calculation is performed. It also adds 'i' in case of even roots of negative numbers.
x = int(input("Please enter an integer: "))
epsilon = 0.01
numGuesses = 0
low = -abs(x)
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 -x) >= epsilon:
print ("low = ", low, "High=", high, "ans=", ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print ("numGuesses =", numGuesses)
print (ans, "Is close to square root of", x)
x = int(input('Enter the number you want to find the root of: '))
root = int(input('Enter the power number: '))
epsilon = 0.01
numGuesses = 0
low = 0.0
high = x #note that u removed max()
guess = (high + low)/2.0 #note u changed ans to guess
while abs(abs(guess**root) - abs(x)) >= epsilon:
print('low =', low, 'high =', high, 'ans =', guess)
numGuesses += 1
if abs(guess**root) < abs(x):
low = guess
else:
high = guess
guess = (high + low)/2.0
print('numGuesses =', numGuesses)
print(guess, 'is close to root of', x)
This works well and there are not a lot of changes from the OG code
Your algorithm is a numerical search through dichotomy method applied to X^2-x=0, it converges (quite fast actually) towards the solution X=sqrt(x) as long as low is lower than the solution, and high is higher than the solution.
In your case x is always higher than sqrt(x) and 0 is always lower than sqrt(x).
The answer will always be in the region being searched,you can lower epsilon as much as you want. There is no point in changing the initialisation of low. If you lower it to negative values, it will only require a few more step, roughly log2(abs(low))
change
ans**2
to
ans**3
and your algorithm converges to the cubic root of x.
The cubic root of negative numbers is not well defined, I guess what they mean is the cubic root of the absolute value, multiplied by -1. So (-3)^3 =-9
If x<0, replace x by abs(x), run the algorithm and return the solution multiplied by -1.
This:
low = 0.0
if low < 0:
low = -low
literally does nothing. You set low = 0 and then check if it's less than 0 (which it isn't). Also, 0 is both positive and negative, so changing its sign does nothing.
I'm afraid I don't understand the problem entirely, but it looks like high and low are bounds within which you expect the square/cubed root to be?
If x is negative then you want to make sure your lower bound can encompass it. Maybe setting low = x would help?
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)