[Tutor] Calculation error with a simple program

Laura Creighton lac at openend.se
Sat Dec 12 10:07:10 EST 2015


I haven't verified this, but you are probably up against some
problem caused by using floating point to store money.

The problem is that, when people see something like the floating
point number, 3.15 they think, aha, this is a decimal number just
like I learned in school when I was 10 years old.  This is 3 plus
one-tenth, plus 5 one hundreths. exactly.  I know everything about this
sort of thing, I learned it when I was 10.

In particular, you probably learned this properly of numbers in
general.

(a + b) + c  = a + (b + c)  (associative properly of addition)

And while you probably had not thought about this property, you
definitely exepected it to work with your 3.15 when you want to add
it to 2.17

And, herein lies the rub.
floating point numbers, despite looking exactly the same as what you
learned in school (A terrible design decision, I think that if we
wrote them 3_15 or 3#15 we would have many fewer problems now, but
it got made before I was born, so .... ) ARE NOT the things you
learned in school.

Not all decimal numbers are exactly representable in floating point.
As a result the law of association fails.  The correct result can 
indeed depend on the order in which you do your operations.

You can read more about this here:
https://docs.python.org/3.5/faq/design.html#why-are-floating-point-calculations-so-inaccurate

and in the tutorial:

https://docs.python.org/3.5/tutorial/floatingpoint.html#tut-fp-issues

This is also good.
http://floating-point-gui.de/

And if you want a more serious, mathematical approach, this ACM reprint is
_really good_, but not to everybody's taste.
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Most of the time, this does not matter, because most of the people
using floating point are scientists.  Scientists, contrary to popular
belief, are not all that concerned with exact accuracy.  Their results
always come with an error estimate.  'the distance is such and such 
+/- 10%' or +/- 0.005%  or what have you.  So, as long as you do
your calculations in such a way that the floating point error is
covered in the % of uncertainty that you have anyway, your answer
is perfectly correct enough for science.

And floating calculations are much, much faster than fixed point
decimal calculations, which in the old days meant the difference
between getting a result for your calculations in a week or in
more than a month.  No wonder the scientists were happy to trade
accuracy which they couldn't use for speed, which they had immediate
need for.

But once you get to calculations with money, you are suddenly out of
the realm of science.  (Even if some economists might want to tell
you different. :) )  Money is exact.   Nobody is willing to accept
10 pounds +/- 10% for a pizza, and allow people to pay anything between
9 pounds and 11 pounds as an ok price.

In python we have a fix for this, called the Decimal object.
Decimals behave the way you want them to -- i.e. the principle of
associaton holds.

https://docs.python.org/3.5/library/decimal.html

So, if you are just noodling around, playing with things, using floats
to store money is ok.  It teaches bad habits, but that battle was 
fought and lost a long time ago.  However, if you want to do something
serious, like keep track of your own financial affairs with python,
***Don't Use Float For Money***.  Please save yourself grief and
use the Decimal type instead.

Laura


More information about the Tutor mailing list