Skip to content Skip to sidebar Skip to footer

Strange Python While Loop Behavior With < Comparison

I'm confused with this snippet of code: t=0 while t<5: #currently loop runs for 10 seconds print 'in loop',t if (t<5): print 'true' t=t+0.01 prints in

Solution 1:

5 isn't necessarily 5:

t=0
while  t<5:  #currently loop runs for 10 seconds
    print "in loop",t, repr(t)
    if (t<5):
        print "true"
    t=t+0.1

produces

in loop 0 0
true
in loop 0.1 0.1
true
in loop 0.2 0.2
true
in loop 0.3 0.30000000000000004

[...]

in loop 4.8 4.799999999999999
true
in loop 4.9 4.899999999999999
true
in loop 5.0 4.999999999999998
true

0.1 can't be represented exactly in binary.

[Ah, I just noticed that I used 0.1 instead of 0.01, like you did. Well, it's the same issue.]

Two "how floating point works" references: classical and gentler.


Solution 2:

The value of t on the last loop iteration is close to, but just under 5.0. It is impossible to represent 0.01 exactly in binary, so a small error creeps in each time 0.01 is added to t. Python deems the result close enough to 5.0 to print "5.0", but it's not actually quite 5.0.

To make it work as you expect, use a Decimal, which does not suffer from these rounding errors.

from decimal import Decimal
t=Decimal("0")
while  t<5:
    print "in loop",t
    if (t<5):
        print "true"
    t=t+Decimal("0.01")

Solution 3:

This is because values are rounded for printing. It is absolutely what one would expect.

If you need to avoid this behaviour, then either format your output differently, or use an appropriate delta to test against, e.g. 5.0 - t < delta

delta is any numeric value you like - it defines how close to 5 is equal to 5 for your purposes, given that in general decimal values cannot be represented exactly using a purely binary representation.

If this is unacceptable in your application, the alternative is to use a decimal class that uses a decimal representation internally.


Solution 4:

The problem is a precision error. If you change this to:

t=0
while  t<5:  #currently loop runs for 10 seconds
    print "in loop",repr(t)
    if (t<5):
        print "true"
    t=t+0.01

you'll see that the last time through the loop t is actually something like 4.999999999999938.

Python (as well as most other programming languages) can't represent all real numbers exactly, so you end up with surprising behavior like this.


Solution 5:

Based on Marcin's recommendation of using a delta, here's a workable solution:

>>> step = 0.01
>>> t = 4.9
>>> while 5.0 - t > step:
        print 'in loop', t
        t += step


in loop 4.9
in loop 4.91
in loop 4.92
in loop 4.93
in loop 4.94
in loop 4.95
in loop 4.96
in loop 4.97
in loop 4.98
in loop 4.99

Post a Comment for "Strange Python While Loop Behavior With < Comparison"