Strange python when working with a loop <comparison

I am confused by this piece 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 the last run of the loop:

 in loop 5.0 true 

Now, if it is true that t = 5.0 on the last pass through the loop, there should not be a condition that t <5 in the if statement is not satisfied? And besides, shouldn't it even go through the loop for t = 5, since it also had to fail the while condition?

+1
source share
6 answers

5 is optional 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 cannot be represented exactly in binary format.

[Ah, I just noticed that instead of 0.1, instead of 0.1 I used 0.1. Well, this is the same problem.]

Two links "how floating point works": classic and gentler .

+3
source

This is because the values โ€‹โ€‹are rounded for printing. This is absolutely what you would expect.

If you need to avoid this behavior, either format your output differently, or use the appropriate delta to check against, for example. 5.0 - t < delta

delta - any numerical value you like - it determines how close to 5 is for your purposes, provided that in general decimal values โ€‹โ€‹cannot be represented exactly using a pure binary representation.

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

+1
source

The value of t at the last iteration of the loop is close, but slightly less than 5.0. It is impossible to represent 0.01 exactly in binary format, so for every 0.01 error a small error is added in t . Python thinks the result is close enough to 5.0 for printing "5.0", but actually it's not really 5.0.

To make it work as you expect, use 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") 
+1
source

The problem is the error of accuracy. 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 will see that the last time through the t loop is actually something like 4.999999999999938.

Python (like most other programming languages) cannot accurately represent all real numbers, so you will get amazing behavior like this.

0
source

Based on Marcin's recommendation to use delta, here you can find a 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 
0
source

Another way to look at this is that 0.1 in binary format is similar to 1/3 in base 10 (i.e. 0.333333). It cannot be represented by a finite number of digits. When you enter 0.1 , Python converts it to binary, but (obviously) does it using a finite number of bits and therefore not exactly 0.1. So, basically, what happens here with a hypothetical computer that works in base 10:

 count = 0 while count != 1: count += 0.33333333333 

Of course, the count will never be exactly 1, and the while will continue to work.

0
source

All Articles