views:

259

answers:

2

Make a new AS3 Document in Flash, paste in the following code and run it:

var a:Number=0;
trace(a)  //  0
a+=0.3;
trace(a)  //  0.3
a+=0.3;
trace(a)  //  0.6
a+=0.3;

trace(a)  //  0.8999999999999999
a+=0.3;
trace(a)  //  1.2
a+=0.3;
trace(a)  //  1.5
a+=0.3;
trace(a)  //  1.8
a+=0.3;
trace(a)  //  2.1
a+=0.3;
          //  ^ This is the output. Notice the inaccuracy starting from 0.9 / 0.89

Why the error? I'm just doing an ordinary hi resolution addition.

Any workarounds?

+7  A: 

This is a standard floating point problem. Binary floating point numbers do not represent the full range of decimal numbers with perfect accuracy, you need to do something along the lines of

trace (round (a, 1))

or, better yet, turn it into a string and strip off everything past the first fractional digit (since the result of round may also not be easily representable in binary).

although I don't know ActionScript. Still it's a very well known issue and not limited to AS3.

See for example http://stackoverflow.com/questions/177506/why-do-i-see-a-double-variable-initialized-to-some-value-like-214-as-2139999961 or http://stackoverflow.com/questions/327544/strange-floating-point-behaviour-in-a-java-program or http://stackoverflow.com/questions/249467/what-is-a-simple-example-of-floating-pointrounding-error.

paxdiablo
A: 

One workaround is to use a scaled integer type. For this example, you could increment by 3, and then divide by 10 just before output. That avoids all the rounding errors inherent in floating point arithmetic.

recursive