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?

Georgy
  • 12,464
  • 7
  • 65
  • 73
Tote99
  • 167
  • 8
  • 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. – Max Apr 18 '20 at 04:37

7 Answers7

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
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
Sunny Patel
  • 194
  • 1
  • 10
4
while True:
    if intensity>0.65:
        break
    print(intensity)
    intensity+=0.05
Darkknight
  • 1,716
  • 10
  • 23
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)
Prune
  • 76,765
  • 14
  • 60
  • 81
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
tenacity
  • 456
  • 1
  • 5
  • 14
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

...

Lavanya V
  • 337
  • 2
  • 7
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
mohammed wazeem
  • 1,310
  • 1
  • 10
  • 26