Friday, October 17, 2008

Redirects and the lack of precision

Okay the redirect plan is out of the window because the mathematical precision isn't good enough and we get into infinite redirect loops... Back to plan A which is to calculate a standard bottom left.

20.5 * 0.2 = 4.10000000000000005

No it ruddy doesn't it is 4.1

20.5 / 5 = 4.0999999999999996

Java is just as bad at this so its not a Python fault (although with Java at least its consistently bad, Python is inconsitently bad as it just defaults to the C implementation on the box).

Technorati Tags: ,

3 comments: said...

>>> from decimal import Decimal
>>> Decimal("20.5")/5
>>> print Decimal("20.5")/5

Rob Eamon said...

This is not a Java problem. It is a binary arithmetic problem, common to all language environments. If you need accuracy, avoid using float and double. The answers you're seeing are "precise" but not "accurate."

"Most terminating decimal fractions cannot be exactly represented as terminating binary fractions."
-- Joe Darcy, Java Floating-Point Czar has an article on floating point.

"[0.1 is a repeater fraction in binary.] It is like the repeater fraction 1/3 = 0.33333 in base 10. When you add 0.333333... to 0.666666... why are you not astonished to get 0.999999... rather than 1.0, even though you just added 1/3 + 2/3 to get 1? Yet, with Java floating point you are astonished when you add 0.1 + 0.1 and get something other than 0.2."

Rob Eamon said...

Additional references on the issue of using binary floating point arithmetic and expecting accuracy:

"...naive use of floating point arithmetic can lead to many problems... Floating point arithmetic is at its best when it is simply being used to measure real-world quantities over a wide range of scales (such as the orbital period of Io or the mass of the proton), and at its worst when it is expected to model quantities expressed as decimal strings that are expected to be exact. An example of the latter case is financial calculations. For this reason, financial software tends not to use a binary floating-point number representation."