0
x = 25
epsilon = 0.01
step = 0.1
guess = 0.0

while guess <= x:
    if abs(guess**2 -x) >= epsilon:
        guess += step

if abs(guess**2 - x) >= epsilon:
    print('failed')
else:
    print('succeeded: ' + str(guess))

I am given this Python program which attempts to calculate the square root of a number x. For some reason, this program loops indefinitely and I'm not sure why.

There are only finitely many values of guess, because, after guess>x (i.e. when guess>=25.1,, the while loop then stops). The while command in the middle of the program is the only thing that loops, so what is happening?

4
  • Put some print statements in and find out Commented Nov 6, 2016 at 21:50
  • So what happens when guess = 5.0? Your if statement won't match but guess <= x still true. Commented Nov 6, 2016 at 21:51
  • You don't stop the loop if the guess is within epsilon. Commented Nov 6, 2016 at 21:52
  • Please have a look at Methods of computing square roots to implement a square root computation algorithm. A naive search is not performant at all. Commented Nov 6, 2016 at 22:02

2 Answers 2

2

You only increment guess when the condition abs(guess**2 -x) >= epsilon is true. That condition is false when guess = 5.0. At that point guess never changes anymore but guess <= x is still true and you enter an infinite loop:

>>> x = 25
>>> epsilon = 0.01
>>> guess = 5.0
>>> abs(guess**2 - x)
0.0
>>> abs(guess**2 - x) >= epsilon
False

Starting at guess = 0.0 and incrementing by 0.1 means that your loop executes 50 times before reaching that point, after which guess never changes again.

In reality, guess is not 5.0 exactly because adding an approximation of 0.1 (which can't be represented exactly using binary fractions), gives you a value a small amount lower:

>>> guess = 0.0
>>> for _ in range(50):
...     guess += 0.1
...
>>> guess
4.999999999999998

but that difference is still smaller than epsilon.

You probably want to break the while loop when you have reached within epsilon distance of the target:

while guess <= x:
    if abs(guess**2 -x) < epsilon:
        break
    guess += step
Sign up to request clarification or add additional context in comments.

Comments

0

Even if you change the while condition to < instead of <=, it will still loop indefinitely, because of floating point inaccuracy.

Although you add steps of 0.1, the guess value will not become exactly 5, but 4.999999999999998, at which point the loop will continue to run without entering in the if block.

This is at least what I see happening here

4 Comments

The stepsize is 0.1, not 0.01. 50 * 0.1 is still 5.0 exactly ((50 * 0.1).is_integer() is true).
Maybe it depends on the processor, because I see it happening here.
No, I can reproduce it when I step away from multiplication and use addition 50 times.
Indeed, I just came to the same conclusion :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.