1

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

5
  • Agreed Precision wil vary... but here 5.5511151231257827e-17 is incorrect!! Commented Dec 12, 2009 at 11:27
  • 3
    While not wanting to take anything away from the answers below, 5.55e-17 is really a small quantity and would be regarded as zero in most practical situations. Commented Dec 12, 2009 at 11:27
  • 2
    In case you don't understand the notation, the number you see means 0.000000000000000055511151231257827. Very small. Commented Dec 12, 2009 at 11:29
  • 6
    0.1 is not representable exactly in any precision of a IEEE-754 floating-point format. You could use 128-bit extended doubles and still have the same problem, only the exponent would be even smaller. Commented Dec 12, 2009 at 11:30
  • 1
    just for fun I tried it in Python, Lua, Perl and Ruby. they all show the same result: 5.55111512312578e-17 Commented Dec 12, 2009 at 11:50

6 Answers 6

14

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
Sign up to request clarification or add additional context in comments.

3 Comments

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.
More precisely, that is how binary floating point numbers work. Numbers represented by the Decimal type in Python are decimal floating point numbers.
Yeah, I could be clearer. By "floating point numbers" I meant the float type in Python.
7

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.

Comments

4

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

Comments

3

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

Comments

2

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

2 Comments

[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
Because System.out.println rounds the number, which is exactly what the Python code in my answer does.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.