0

If I type the following into either the Python 2.7.1 shell or the 3.3.2 shell:

a = 0.1
b = 0.1
(a + b) == 0.2

it returns the value true. From stackoverflow and this video from MIT, I was under the impression that this would return false, since there are small errors when trying to represent 0.1 exactly in a computer. (Isn't it binary after all?) So I guess Python must be either a) doing non-floating point arithmetic or b) rounding before doing a test for equality.

Which is it and which versions of Python have this behavior?

Chris Middleton
  • 5,654
  • 5
  • 31
  • 68

2 Answers2

6

None of them. It's "luck". The floating point representation+arithmetic gives the same value for the numbers you picked.

>>> (0.1 + 0.1) == 0.2
True
>>> (0.1 + 0.2) == 0.3
False

You can use the decimal module to show you this:

>>> import decimal
>>> decimal.getcontext().prec = 60
>>> decimal.Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> decimal.Decimal(0.2)
Decimal('0.200000000000000011102230246251565404236316680908203125')
>>> decimal.Decimal(0.1) + decimal.Decimal(0.1)
Decimal('0.2000000000000000111022302462515654042363166809082031250')
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • Can't accept answer yet - otherwise I would. One more question: how can I see the "actual" representation of 0.1 or 0.2? I know that using print statements rounds the answer, but even when I just type `0.1` into the interpreter, it simply spits out `0.1`. ** EDIT: I see you already were about to answer this very question. Thanks! – Chris Middleton Dec 28 '13 at 23:07
  • 3
    @AmadeusDrZaius, current versions of Python display the shortest decimal string that will, when read back in, reproduce the float exactly. So many decimal strings you type in will get echoed back at you verbatim. – Tim Peters Dec 28 '13 at 23:10
  • @TimPeters Gotcha. Thanks, Tim! – Chris Middleton Dec 28 '13 at 23:10
  • Part of the "luck" is that `x + x` is always an exact operation in binary (unless overflow). – dan04 Jan 09 '14 at 00:41
4

A bit of a deeper explanation: 0.1 decimal can't be represented exactly as a finite binary float, so both instances of 0.1 introduce small errors (less than 1 part in 2**53, because there are 53 bits of precision in a Python float on almost all machines, and Python does best-possible rounding). But floating addition is also subject to its own rounding error. Sometimes the errors cancel out.

So "luck" is an accurate enough description. If you want to use unbounded rationals instead, see the docs for the standard fractions module.

Tim Peters
  • 67,464
  • 13
  • 126
  • 132