3

when i try to check whether float variable contain exact integer value i get the folowing strange behaviour. My code :

x = 1.7  print x,  (x == int(x))   
x += 0.1  print x,  (x == int(x))
x += 0.1  print x,  (x == int(x))
x += 0.1  print x,  (x == int(x))
print "----------------------"

x = **2.7** print x,  (x == int(x))
x += 0.1  print x,  (x == int(x))
x += 0.1  print x,  (x == int(x))
x += 0.1  print x,  (x == int(x))

I get the folowing strange output (last line is the problem):

1.7 False
1.8 False
1.9 False
2.0 True
----------------------
2.7 False
2.8 False
2.9 False
3.0 False

Any idea why 2.0 is true and 3.0 is false ?

AlG
  • 14,697
  • 4
  • 41
  • 54
yzahavi
  • 45
  • 2
  • [This is relevant reading from the docs.](https://docs.python.org/2/tutorial/floatingpoint.html) – SuperBiasedMan Aug 17 '15 at 14:18
  • 1
    [Is floating point math broken?](http://stackoverflow.com/q/588004/995714). http://floating-point-gui.de/, [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – phuclv Aug 17 '15 at 14:35

1 Answers1

10

the problem is not with conversion but with addition.

int(3.0) == 3.0

returns True

as expected.

The probelm is that floating points are not infinitely accurate, and you cannot expect 2.7 + 0.1 * 3 to be 3.0

>>> 2.7 + 0.1 + 0.1 + 0.1
3.0000000000000004
>>> 2.7 + 0.1 + 0.1 + 0.1 == 3.0
False

As suggested by @SuperBiasedMan it is worth noting that in OPs approach the problem was somehow hidden due to the use of printing (string conversion) which simplifies data representation to maximize readability

>>> print 2.7 + 0.1 + 0.1 + 0.1 
3.0
>>> str(2.7 + 0.1 + 0.1 + 0.1)
'3.0'
>>> repr(2.7 + 0.1 + 0.1 + 0.1)
'3.0000000000000004'
lejlot
  • 64,777
  • 8
  • 131
  • 164
  • 3
    Worth noting that the distinction isn't shown clearly because `print` will ignore the discrepancy for the sake of readability but if you were to use `repr(2.7 + 0.1 + 0.1 + 0.1)` it would show the true value. – SuperBiasedMan Aug 17 '15 at 14:17
  • 1
    **Correction** A more accurate value, it will still ignore a certain number of decimal places. – SuperBiasedMan Aug 17 '15 at 14:23