Why does 0.1 + 0.1 + 0.1 - 0.3
evaluates to
5.5511151231257827e-17
in Python?
views:
243answers:
6Because 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
Because of the way floating points numbers are represented in a computer. It's not just a Python thing.
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.
The answer is here: What Every Computer Scientist Should Know About Floating-Point Arithmetic
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.
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