# [Tutor] quick question

Steven D'Aprano steve at pearwood.info
Fri Sep 28 14:41:44 CEST 2012

On 28/09/12 19:03, Mark Lawrence wrote:
> On 28/09/2012 06:18, jh wrote:
>
> [snip]
>
>> The subtotal of your items is: 26010.850000000002
>> The total amount of your items plus tax is: 27,571.50
>>
>> My question here is, why does my subtotal have so many decimals when I never
>> went above 2 in my input?
>>
>> J
>
>found the answer a lot faster, as this has been asked umpteen times on Python
>  lists alone.

And I'm sure it will be asked a bazillion more times :/

> Also note that if you'd have formatted the output in the same way that you
>did for the total you'd never have noticed.

That's not strictly true, and by that I mean it's completely wrong :) String
formatting can only hide so much.

There are many ways to stumble over binary floating point issues. For example,
this is using Python 3.2 which tries really hard to print a sensible float
approximation for you:

py> d = 1/10
py> numbers = [d]*10
py> print(numbers)
[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]

Here we have 0.1 repeated ten times. So if we add them, we ought to get one,
right?

py> total = sum(numbers)
py> total == 1
False

What's going on? If we look at the total, we see that it adds up to slightly
*less* than the expected one:

py> print(total)
0.9999999999999999

But if we print 0.1 in full precision, we see that it is slightly *greater*
that 0.1 in decimal:

py> print("%.17f" % d)
0.10000000000000001

So that's TWO nasty surprises (so far) with binary floating point numbers:

* not all "nice" decimal numbers, like 0.1, can be stored exactly in a
binary float;

* and when you add ten numbers slightly greater than 0.1, the result can
actually be less than 1.0 !!!

Welcome to binary floating point hell. And this has nothing to do with
Python, the same thing happens in *any* language with binary floats.

--
Steven