views:

243

answers:

6

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

+15  A: 

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
Lukáš Lalinský
Exactly ... and since the other numbers were only specified to 1 decimal place, you can't seriously expect to display 17 decimal places in the answer.
pavium
More precisely, that is how *binary* floating point numbers work. Numbers represented by the Decimal type in Python are decimal floating point numbers.
dangph
Yeah, I could be clearer. By "floating point numbers" I meant the `float` type in Python.
Lukáš Lalinský
+2  A: 

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

Pablo Santa Cruz
[Quote]class Flt{ public static void main(String args[]) { float w,x,y,z,ans; w=0.1f; x=w; y=w; z=0.3f; ans=w+x+y-z; System.out.println(ans); }}[/Quote]In java gives 0.0
Myth17
Because `System.out.println` rounds the number, which is exactly what the Python code in my answer does.
Lukáš Lalinský
+7  A: 

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.

Claudiu
+4  A: 

The answer is here: What Every Computer Scientist Should Know About Floating-Point Arithmetic

alygin
A: 

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.

outis
+3  A: 

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
Martin Geisler