Question

Why does 0.1 + 0.1 + 0.1 - 0.3 evaluates to 5.5511151231257827e-17 in Python?

Was it helpful?

Solution

Because that's how floating point numbers work. If you want precise numbers, use the decimal module. If you want to use floating point numbers, you have to remember to round them to a specific precision when you are displaying them.

>>> print '%.2f' % (0.1+0.1+0.1-0.3,)
0.00

OTHER TIPS

This is a problem with floating point numbers in general. See this section on Wikipedia for a description. Roughly speaking - there are rounding errors. Notice that the number you gave us was very small - about 0.00000000000000005551115123 . Here is a more technical paper about the subject.

You might be interested in knowing that Python 3 has improved the situation by changing how repr works. It will now give you the shortest string representation that will be converted back to the original float:

Python 3.1.1+ (r311:74480, Oct 11 2009, 20:19:13) 
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1
'0.1'

Older versions behave like this:

Python 2.6.4 (r264:75706, Oct 28 2009, 22:19:17) 
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1
'0.10000000000000001'

It is only the output of repr (called implicitly when you enter a value in the interactive interpreter) that has changed. The underlying values are still IEEE-754 floating-point numbers, and they still have the usual limitations:

Python 3.1.1+ (r311:74480, Oct 11 2009, 20:19:13) 
[GCC 4.3.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1
0.1
>>> 0.2
0.2
>>> 0.3
0.3
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 - 0.3
5.551115123125783e-17

Because of the way floating points numbers are represented in a computer. It's not just a Python thing.

As an example, consider representing 1/3 as a scientific number in base 10. With only a finite number of digits (say, 10), you'll wind up with a rounding error. Say 1/3 ≈ 0.3333333333e0. Then 1/3+1/3+1/3 (after first converting to decimal expansions) is represented as 0.9999999999e0, but 1 is 1.0e0. Similarly, 1/7 ≈ 0.1428571429e0, and 1/7+1/7 would be 0.2857142858e0, but the representation for 2/7 would be 0.2857142857e0. In both cases, the sum is off by 1e-10.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top