4

Why exactly does the latter case in Python doesn't yield the result 3.3?

>>> 1.0 + 2.3
3.3
>>> 1.1 + 2.2
3.3000000000000003

It doesn't seem to make any sense to me what is going on here. What are the limitations here for the representation of the same result that you are getting through 1.0 + 2.3 but not through 1.1 + 2.2?

cpx
  • 17,009
  • 20
  • 87
  • 142
  • 1
    Its a tough read, but this will help you understand what is going on: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Jason Sperske Oct 24 '13 at 18:01
  • 4
    Floating point numbers are, generally speaking, not exact representations of decimal numbers, but approximations. To get exact representations of decimal numbers, see http://docs.python.org/2/library/decimal.html – Robert Harvey Oct 24 '13 at 18:01
  • 2
    @JasonSperske: I'd say that's recommended reading for anyone being able to rake in 5k in SO rep and wonder about this. – Benjamin Bannier Oct 24 '13 at 18:44

1 Answers1

9

To quote the documentation:

Unfortunately, most decimal fractions cannot be represented exactly as binary fractions. A consequence is that, in general, the decimal floating-point numbers you enter are only approximated by the binary floating-point numbers actually stored in the machine.

And what you have stumbled upon is one of many idiosyncrasies:

>>> 1.1 + 1.1
2.2
>>> 1.1 + 2.3
3.4
>>> 1.1 + 2.2
3.3000000000000003

In fact, its a rare one, I've had a hard time finding other occurrences. Here's another weird one:

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17

Using Python's decimal class would give you better results.

Games Brainiac
  • 80,178
  • 33
  • 141
  • 199
  • or the decimal module – Ant Oct 24 '13 at 18:40
  • 2
    I gave you +1 but `numpy` is not a good solution here. `numpy` still uses binary floats. The `decimal` library would provide an exact solution here, as `decimal` operates exactly on decimal values. – steveha Oct 24 '13 at 18:41
  • I thought python just usually uses IEE754, and numpy probably, too. Could you give an example? Maybe you were thinking of e.g. `sympy.mpmath`. – Benjamin Bannier Oct 24 '13 at 18:41
  • 1
    +1 for `0.1 + 0.1 + 0.1 - 0.3` :) – JadedTuna Oct 24 '13 at 18:48
  • @steveha @Benjamin You guys are right. It was my mistake, I thought numpy had more precision, but that turns out to be not entirely true. `Decimal` _is_ more precise, but its not all that precise either. – Games Brainiac Oct 25 '13 at 06:34
  • Well, `numpy` does offer several precisions of float, including `float64` and even `float96`. So arguably it can be more precise. But any binary float representation will be unable to exactly represent certain decimal fractions such as `0.1`. (`0.5` is of course easy in binary float format.) To put it another way: you already know that you cannot express `1/7` in any finite length decimal; no matter how many decimal places you write, you never reach the end of the fraction. Well, binary fractions have the same problem with some decimal numbers. – steveha Oct 25 '13 at 06:40
  • 1.1*3 , 1.1*4, 1.1*2 – ASHMIL Jan 10 '21 at 16:51
  • How should I use `decimal` class? `Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)` gives `Decimal('2.775557561565156540423631668E-17')` output – alper Jul 17 '21 at 12:08