Infinite while loop when checking floats for equality [duplicate]
Asked Answered
D

7

12

I'm having an infinite loop when I run this code:

intensity = 0.50
while intensity != 0.65:
    print(intensity)
    intensity = intensity + 0.05

intensity values should be like 0.50 -> 0.55 -> 0.60 -> 0.65 then it should gets out of the loop. Why the program is doing an infinite loop instead?

Directions answered 18/4, 2020 at 4:32 Comment(1)
For one thing, you get floating-point errors, so at the second iteration intensity is 0.6000000000000001 and the loop never closes. Rounding would fix this. However, I don't know why it isn't printing the value, so I have upvoted your question.Dg
A
9

Because of floating point imprecision, you may not end up with exactly 0.65.

To solve this, use < rather than != (a):

intensity = 0.50
while intensity < 0.65:
    print(intensity)
    intensity = intensity + 0.05

The output of that (showing what I mean by imprecision as well) is:

0.5
0.55
0.6000000000000001

If you kept going, you'd see:

0.6500000000000001
0.7000000000000002
0.7500000000000002
0.8000000000000003

which is why it's never equal to 0.65.


(a) You may be wondering what the situation would be if the next value was 0.6499...9 rather than 0.650..1, and you would probably be right to be concerned.

While using < will fix the latter case, you'll almost certainly get one iteration too many for the former case.

You can fix that by a number of possible different strategies, some of which are:

  • round the number to the correct number of decimals before comparing, such as round(intensity, 2).
  • compare it with a "close enough" check, such as the absolute difference being less that 10-4 (for example) - something like if abs(intensity - 0.65) < 0.0001.
  • use integral values exclusively and scale the value as needed (e.g., initialising intensity to 50, adding 5, comparing to 65, and printing round(intensity / 100, 2).

The Python documentation has an interesting article that you can read to further understand these limitations.

Adanadana answered 18/4, 2020 at 4:37 Comment(0)
J
4

This is due to the way Python (and some other languages like C) handle floating-point provisions. See this or this. In general, you should avoid floating point loop counters.

If you still wanted to use one, you can round it off:

intensity = 0.50
while round(intensity,2) != 0.65:
    print(round(intensity,2))
    intensity = intensity + 0.05
Jornada answered 18/4, 2020 at 4:38 Comment(0)
L
4
while True:
    if intensity>0.65:
        break
    print(intensity)
    intensity+=0.05
Lorileelorilyn answered 18/4, 2020 at 5:34 Comment(0)
F
3

Look at your output:

0.5
0.55
0.6000000000000001
0.6500000000000001
0.7000000000000002

0.05 cannot be exactly represented with a terminating binary float number.

See is floating point math broken?

If you want to check whether the value is close, then simply set your desired tolerance:

while abs(intensity - 0.65) < my_tolerance:

Better yet, use the built-in function, setting either relative or absolute tolerance:

isclose(intensity, 0.65, rel_tol=1e-9, abs_tol=0.0)
Fuji answered 18/4, 2020 at 4:40 Comment(0)
H
3

Quickly editing your code to observe how intensity increases:

from time import sleep

intensity = 0.50
while intensity != 0.65:
    print("The intensity is:", intensity)
    intensity = intensity + 0.05
    sleep(5)

This gets stuck in an infinite loops since, the value of intensity never reaches 0.65
The O/P is as follows:

The intensity is: 0.5
The intensity is: 0.55
The intensity is: 0.6000000000000001
The intensity is: 0.6500000000000001
The intensity is: 0.7000000000000002
The intensity is: 0.7500000000000002
The intensity is: 0.8000000000000003
The intensity is: 0.8500000000000003
The intensity is: 0.9000000000000004
The intensity is: 0.9500000000000004
The intensity is: 1.0000000000000004
...
...
Process finished with exit code -1
Hotchkiss answered 18/4, 2020 at 4:43 Comment(0)
B
3

i tried running the following code and the output was

intensity = 0.50
>>> n = 1
>>> while intensity!=0.65 and n<7:
...     print(intensity)
...     intensity = intensity + .05
...     n = n+1

output

0.5
0.55
0.6000000000000001
0.6500000000000001
0.7000000000000002
0.7500000000000002

the loop turns infinite because the 4th output is not exactly .65 it is .65000000001.

try this one and it will work

while float(str(intensity)[:4])!=0.65 :
...     print(intensity)
...     intensity = intensity + .05

...

Baisden answered 18/4, 2020 at 4:51 Comment(0)
L
3

You can avoid this behaviour by using the python built-in round function. The round function will round a number to a given precision in decimal digits.

So you can try something like this

>>> intensity = 0.50
>>> 
>>> while intensity != 0.65:
...     print(intensity)
...     intensity = round(intensity + 0.05, 2)
0.5
0.55
0.6
Latialatices answered 18/4, 2020 at 5:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.