Steve Smith
Steve Smith

Reputation: 101

Why does this Python program loop indefinitely?

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?

Upvotes: 0

Views: 225

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121486

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

Upvotes: 2

trincot
trincot

Reputation: 350137

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

Upvotes: 0

Related Questions