This question already has answers here:
How to find cube root using Python? [duplicate]
(3 answers)
Closed 5 years ago.
So I'm a complete beginner (like less than a week) and wrote this code in python. It's supposed to find the cuberoot of a number if the solution is an integer, and approximate it otherwise. It does both instead of just one or the other. I've tried it multiple ways for hours now but it doesn't work. Any suggestions?
cube=int(input("what number's cube root do you want to find"))
epsilon = 0.01
increment = 0.0001
num_guesses = 0
for guess in range(cube+1):
if guess**3 == cube:
guess += 1
print (guess)
else:
guess1 = 0.0
while abs(guess1**3 - cube) >= epsilon:
guess1 += increment
num_guesses += 1
print('num_guesses =', num_guesses)
else:
print(guess1)
The problem is your indentation. Everything in your "else" statement needs to be indented to show that it is inside the "else" statement. You also have a few logical errors in your code. If you have found a number that, when cubed, is the desired number, you should print that number, not that number plus 1. And if you've found the solution, your program should stop there.
for guess in range(cube+1):
if guess**3 == cube:
print (guess)
return
guess1 = 0.0
Here is the working solution:
cube=int(input("what number's cube root do you want to find: "))
epsilon = 0.01
increment = 0.0001
num_guesses = 0
int_result_found = False
for guess in range(cube+1):
if guess**3 == cube:
print guess
int_result_found = True
break
if not int_result_found:
guess1 = 0.0
while abs(guess1**3 - cube) >= epsilon:
guess1 += increment
num_guesses += 1
#print 'num_guesses =', num_guesses
print(guess1)
As Erik said, there were some errors in your code. Key point is to stop after you've found integer solution, I've used boolean flag int_result_found for that.
One of the problems with you code is indenting. Python requires specific spacing in order to work properly.
The easiest way to avoid getting both answers is to create a boolean variable (I used "found_answer") to check if it is necessary to run the second code.
I've fixed you code, modifying it as little as possible:
cube=int(input("what number's cube root do you want to find"))
found_answer = False
for guess in range(cube+1):
if guess**3 == cube:
print ("integer answer:", guess)
found_answer = True
if found_answer == False:
epsilon = 0.01
increment = 0.0001
num_guesses = 0
guess1 = 0.0
while abs(guess1**3 - cube) >= epsilon:
guess1 += increment
num_guesses += 1
print('num_guesses =', num_guesses)
print("approximate answer:", guess1)
For your interest, here is a much more efficient solver:
# target function: y = x**3
def cube(x):
return x * x * x
def diff(f, epsilon = 0.001):
"""
Given function f, return a numeric approximation function for f'(x)
"""
def df(x):
return (f(x + epsilon) - f(x)) / epsilon
return df
def newton_solver(target_y, f, df = None, start_x = None, epsilon = 0.001, max_reps = 40):
"""
Newton Raphson approximation
Given real target_y and function f,
return real x such that f(x) = target_y +/- epsilon
"""
# if no differential function is provided, use a numeric approximation
if df is None:
df = diff(f)
# if no starting point is given, guess f(x) ='= x
if start_x is None:
x = target_y
else:
x = start_x
for _ in range(max_reps):
y = f(x)
err = y - target_y
if abs(err) < epsilon:
# close enough
return x
else:
# project the tangent to find a closer approximation
x -= err / (df(x) or epsilon)
# no answer found, bail out
raise ValueError("max_reps exceeded, no solution found")
def main():
y = int(input("What integer do you want to find the cube root of? "))
# find x such that y == x**3
approx_x = newton_solver(y, cube)
# round to the nearest integer
int_x = round(approx_x)
if cube(int_x) == y:
print("The exact cube root of {} is {}.".format(y, int_x))
else:
print("The cube root of {} is approximately {}.".format(y, approx_x))
if __name__ == "__main__":
main()
when it comes to "guess**3 == cube", I think you need to "break"
try this:
cube=int(input("what number's cube root do you want to find"))
epsilon = 0.01
increment = 0.0001
for i in range(cube + 1):
if i**3 == cube:
# break the loop
break
elif (i+1)**3 > cube > i**3: # this is to reduce unnecessary calculations
while (abs(i**3 - cube) >= epsilon):
i += increment
break
print(i)
and I'd like to make it a func:
cube=int(input("what number's cube root do you want to find"))
epsilon = 0.01
increment = 0.0001
def cuberoot(cube):
for i in range(cube + 1):
if i**3 == cube:
break
elif (i+1)**3 > cube > i**3:
while (abs(i**3 - cube) >= epsilon):
i += increment
break
return i
print(cuberoot(cube))
and what is more easy:
def cuberoot(cube):
return cube**(1/3)
Related
this code is supposed to take slope (m) and y-intercept (b) of two lines and checks if these two line hit each other or not.
the problem is my while loop is infinite although I have condition and break statement
print("enter the first m: ")
m = input() # m = slope
print("enter the first b: ")
b = input() # b = y-intercept
print("enter the second m: ")
m1 = input()
print("enter the second b: ")
b1 = input()
sub_m = int(m) - int(m1) #sub = subtract
sub_b = int(b) - int(b1)
if (sub_m == 0):
print("parallel")
x = float(-sub_b / sub_m)
r = round(x, 1)
i = 0.0
while i != r:
print(r, i)
if (i == r):
print("\nhit piont: ", i)
break
if (sub_m > 0 and sub_b > 0):
i -= 0.1
elif (sub_m < 0 and sub_b < 0):
i -= 0.1
else:
i += 0.1
Everyone here seems to be adamant on using some fancy tricks to make floating comparison works. Why not just multiply it all by 10 and get rid of floats altogether? :-)
I don't know if it is the fastest solution but it should have less corner cases.
i = 0
while True: # <- condition removed to allow the "hit point" if to work
print(r, i / 10)
if (i == r * 10):
print("\nhit piont: ", i / 10)
break
if (sub_m > 0 and sub_b > 0):
i -= 1
elif (sub_m < 0 and sub_b < 0):
i -= 1
else:
i += 1
Running this in my debugger showed that you're getting floating point representation errors. This means that although technically you should be getting numbers perfectly rounded to 1 decimal given that you're applying increments of 0.1, in reality this isn't the case:
As you can see, r = -2.0 and i = -2.00...4, thus at no point is r == i.
You can fix this by adding another round statement at the end:
print("enter the first m: ")
m = input() # m = slope
print("enter the first b: ")
b = input() # b = y-intercept
print("enter the second m: ")
m1 = input()
print("enter the second b: ")
b1 = input()
sub_m = int(m) - int(m1) #sub = subtract
sub_b = int(b) - int(b1)
if (sub_m == 0):
print("parallel")
x = float(-sub_b / sub_m)
r = round(x, 1)
i = 0.0
while i != r:
print(r, i)
if (sub_m > 0 and sub_b > 0):
i -= 0.1
elif (sub_m < 0 and sub_b < 0):
i -= 0.1
else:
i += 0.1
i = round(i, 1) # <- this
print(f"Hit pt: {i}")
HOWEVER: This is still error prone, and I recommend finding a way to avoid if i==r altogether in the code. If i is lower than r, exit the loop when it finally becomes bigger, and viceversa. Its best practice to avoid using the == condition when comparing floats, and to find a way to use <= and >=.
This is a question of granularity and floating-point precision. You're incrementing i in steps of 0.1 and then checking, at each step, if i == r. But what if r is not an integer multiple of 0.1? Then i will never exactly equal r, and your break will never be triggered.
By the way, your while condition and your if condition are mutually exclusive; if i and r are equal, you never enter the loop, and consequently won't have to/be able to break out of it. What you want is probably a genuine infinite loop with while True.
First of all, your while loop breaking condition contradicts your if() break condition. so it will never get to match the if condition. So it will never print hit point, because it will break the while loop when l==r, either it will never be l==r because of precision and loop infinite, so in both situations if condition never match. And comparing a floating value to break a loop is not ideal.
I am trying to write a code (python) that uses the Babylonian square root equation by usimg a while loop to approximate square root until error is less than an epsilon value and I am trying to print the approximations in the form [x1,x2,x3...] but have only managed to get the approximations to be listed vertically downwards each on a separate line
e.g.
x1
x2
x3
This is my code so far. I am new to coding so any help and advice would be much appreciated :)
a= float(input('enter the positive value that you wish to find the babylonian square root of '))
e= float(input('enter a positive value for maxium error '))
x= float(input('enter an arbitrary starting value '))
if a<0 or a==0:
print(' a must be a positive number')
elif e<0 or e==0:
print('e must be a positive number')
elif x==0:
print('starting value cannot be 0 as cant divide by 0!')
else:
while abs(x**2-a)>e or abs(x**2-a)==e :
x=0.5*(x-(a/x))
xn=0.5*(x-(a/x))
x=xn
print(x)
Create a list and then output the list:
a = float(input('enter the positive value that you wish to find the babylonian square root of '))
e = float(input('enter a positive value for maxium error '))
x = float(input('enter an arbitrary starting value '))
if a < 0 or a == 0:
print(' a must be a positive number')
elif e < 0 or e == 0:
print('e must be a positive number')
elif x == 0:
print('starting value cannot be 0 as cant divide by 0!')
else:
result_list = []
while abs(x ** 2 - a) > e or abs(x ** 2 - a) == e:
x = 0.5 * (x - (a / x))
xn = 0.5 * (x - (a / x))
x = xn
result_list.append(x)
print(result_list)
I'm trying to program a function to compute Newton's method. Expect I keep getting an error in my code.
This is the prompt that I was given to write a code for
And this is my code that I have written down
import math
def newton(x):
tolerance = 0.000001
estimate = 1.0
while True:
estimate = (estimate + x / estimate) / 2
difference = abs(x - estimate ** 2)
if difference <= tolerance:
break
return estimate
def main():
while True:
x = input("Enter a positive number or enter/return to quit: ")
if x == '':
break
x = float(x)
print("The program's estimate is", newton(x))
print("Python's estimate is ", math.sqrt(x))
main()
And it seems to be working but I keep getting this error when I run checks on Cengage
I'm not really sure what it means because my code seems to be running just fine. Can anyone help explain this?
The issue seems to occur when the input is blank. A potential workaround, assuming you would only want positive numbers as input, would be to set a negative number (or anything else of your choice), like -1 for example, as an exit condition:
x = input("Enter a positive number or enter/return to quit: ")
if not x:
break
x = float(x)
This should avoid the EOFError.
Edit
If you want to use a blank input (hitting the return line) to break out of the loop, you can try this alternative syntax:
x = input("Enter a positive number or enter/return to quit: ")
if not x:
break
x = float(x)
The not x checks if x is blank. It is also more pythonic than x == "". Additional methods to detect a blank input are in this post as well: How do you get Python to detect for no input.
I did mine like this and Cengage accepted it.
import math
tolerance = 0.000001
def newton(x):
estimate = 1.0
while True:
estimate = (estimate + x / estimate) / 2
difference = abs(x - estimate ** 2)
if difference <= tolerance:
break
return estimate
def main():
while True:
x = input("Enter a positive number or enter/return to quit: ")
if x == "":
break
x = float(x)
print("The program's estimate is", newton(x))
print("Python's estimate is ", math.sqrt(x))
if __name__ == "__main__":
main()
The question is
To find the square root of number āNā.using this procedure, we must implement the
following process:
Guess a value for the square root of N
Divide N by that guess
Average the result with your original guess to get your new guess
Go to step 2 and repeat
I have set the code to return the Guess once it is within 0.5 of the previous Guess, and if its not to repeat the function. I'm not sure how to make it repeat or how to close the loop.
def SqrRt(Number,Guess):
while Guess2 == ((Estimate+Guess)/2):
if (Estimate - Guess2) <= 0.5:
return Guess2
elif (Estimate - Guess2) >= -0.5:
return Guess2
else:
Estimate = (Number/Guess)
Guess2 = Estimate + 1
answer = SqrRt(34567823321421,500000)
print(answer)
Using the Babylonian Method means solving (S^2 - V) = 0. Here, S is the square root of V, which is to be found. Applying Newtons Approximation leads to an iterative method where 'x_new = (x_prev + V / x_prev) / 2'. The first 'x_prev' needs to be estimated.
The iteration converges monotonously. Thus a check against a delta in development is sufficient.
x = V / 2.0 # First estimate
prev_x = x + 2 * Delta # Some value for that 'while' holds
while abs(prev_x - x) > Delta:
prev_x = x
x = (x + V/x) / 2.0
square_root = x
Choose Delta to be arbitrarily small (e.g. 0.0001).
First off
You need code that will actually run at all for a question like this. I suggest that your code should look more like this:
def SqrRt(Number,Guess):
while Guess2 == ((Estimate+Guess)/2):
if (Estimate - Guess2) <= 0.5:
return Guess2
elif (Estimate - Guess2) >= -0.5:
return Guess2
else:
Estimate = (Number/Guess)
Guess2 = Estimate + 1
answer = SqrRt(34567823321421,500000)
print(answer)
#Number to Use - 34567823321421
#Answer - 5879440.732
So I am trying to write a file consisting of two recursive functions. One of which calculates the factorials required for approximating sine via taylor series. The second is another recursive function that will output the value of sine as a float value and will go as far as the amount of terms inputted. Here is a mathematical representation of what I am aiming to get
Here is my code so far (it is unfinished as I am having difficulties with the actual sine computation function):
def main():
ang = int(input("Enter the angle to approximate (in radians): "))
trms = int(input("Enter the amount of terms to compute: "))
sinApprox(ang,trms)
def calcFac(x):
if x <= 0:
return 1
else:
return x * calcFac(x-1)
def sinApprox(angle, terms):
if calcFac(terms) <= 0:
return (sinApprox(angle,terms)/calcFac(terms))
elif terms % 2 == 0:
return sinApprox(angle**)
Note that both functions must be pure and recursive as well.
Here is a way that this can be done.
def calcFac(x):
if x == 1 or x == 0: return 1
val = 1
for i in range(2, x+1):
val = val * i
return val
def sinApprox(angle, terms):
mult = 1
if terms % 2 == 0: mult = -1
power = 2*terms - 1
val = angle ** power
val = mult * val/calcFac(power)
if terms == 1: return val
else: return val + sinApprox(angle, terms - 1)
angle = int(input("Enter the angle to approximate (in radians): "))
terms = int(input("Enter the amount of terms to compute: "))
sinApprox(angle, terms)