
Math in JavaScript: Broken Irrational Numbers - fallat
http://ecc-comp.blogspot.com/2016/06/math-in-javascript-broken-irrational.html
======
weinzierl
You don't need to summon irrational numbers to get _wrong_ results.

For example: 0.3-(3*0.1) is non-zero, no irrational numbers involved.

The reason for this is that 1/3 cannot be precisely represented in decimal but
(maybe somewhat surprisingly) it can be in binary, hence the correct result
for 1/3 + 1/3 + 1/3 = 1. On the other hand 1/10 or 0.1 has no precise
representation in binary and is round. The rounding adds up and you get wrong
results.

This also has nothing to do with Javascript but is a consequence of the way
numbers are represented in a computer. Most programming languages deal with
numbers roughly the same way and will be affected by this types of problems.
Some try to hide their shady slopes though. Microsoft Excel has some
heuristics that fudges the results for simple formulas, so you get different
result depending on the heuristic.

For a more detailed explanation see the classic " What Every Programmer Should
Know About Floating-Point Arithmetic" [1]

[1]
[http://www.phys.uconn.edu/~rozman/Courses/P2200_14F/download...](http://www.phys.uconn.edu/~rozman/Courses/P2200_14F/downloads/floating-
point-guide-2014-11-03.pdf)

~~~
tzs
> The reason for this is that 1/3 cannot be precisely represented in decimal
> but (maybe somewhat surprisingly) it can be in binary, hence the correct
> result for 1/3 + 1/3 + 1/3 = 1.

1/3 cannot be precisely represented in (finite) binary. Its representation is
0.0̅1̅.

~~~
tzs
(This was meant to be appended as an edit to the above, but between the time I
started typing it into the update text area and the time I hit the "update"
button the comment aged enough to not allow updates, so I'll add it as a
reply)

In general, a necessary (but not sufficient) condition for the representation
of n/m to be precisely represented in base b is that there exists some integer
r in [1, m-1] such that rb = 0 mod m. If you work out the representation of
n/m using the classic division algorithm, the algorithm terminates iff you hit
such an r after one of the subtraction steps. The step on which you hit that r
will have produced the next to less digit of the result, and then the
algorithm will product one more digit and terminate.

When m is a prime (such as m = 3), then (r, m) = 1, and so rb = 0 mod m is
only possible if b = 0 mod m. If b = 0 mod m then all r are suitable, and n/m
has at most one digit after the radix point.

