Javascript geometric methods: zero is not exactly zero, is it?

In a simple geometric program written in Javascript and Canvas, when I set the angle to 270 Β° (1 & frac12; & pi;), I expected Math.cos (& theta;) to reach zero. The vector is right down from the center, there is no distance on the carted grid. Instead, I get the following:

demo_angle = 270 ang = demo_angle * Math.PI / 180 x = Math.cos(ang) console.log(x) > -1.836909530733566e-16 

To view the output of math functions, view the console. The source code is displayed (in coffeescript) one level up at the URL.

I needed to define in my code, "Any number whose absolute value is less than 1e-15 should be considered zero", but this is really unsatisfactory. Of course, when I try to do the math with a lower x value, especially since I try to use x as the denominator in calculating the slope, and then doing quadratic manipulations, I end up coming up with numbers that exceed Number.MAX_VALUE (or Number.MIN_VALUE )

I know floating point math, at the assembler level, a bit of a dark art, but results like this seem weirder than acceptable. Any hints on what I should do?

+4
source share
2 answers

The problem is not that "zero is not exactly zero." On the contrary, zero is zero.

The problem you are facing is that 3Ο€ / 2 is not represented as a floating point number. So you are actually taking the cosine of a value that is not exactly 3Ο€ / 2. How big is this misconception? Around 1.8e-16, which is the source of the error that you see in cosine.

Some languages ​​work around this problem by providing features such as sinpi and cospi that implicitly scale their arguments with the factor Ο€; This is one way to achieve accurate results. Obviously, this is not an option for you, because javascript does not have such functions. You can collapse your own if you want, using the symmetries of these functions, or you can simply clamp the "almost zero" values ​​to zero, as now. None of them are particularly satisfactory, but both of them are likely to work for your purposes.

+9
source

The problem is that Math.PI is not exactly equal to Pi, but instead is the form number m * 2 ^ e with 2 ^ 52 <= m <2 ^ 53 closest to it.

Multiplying by 270 introduces a slight rounding error.

Then dividing by 180 leads to some rounding error.

So your ang value is not exactly 3 * Pi / 2, and as a result, you will not return to the expected 0.

The calculation itself is very accurate.

+3
source

All Articles