4

I don't understand, why I get some very strange values from trigonometric functions in JavaScript. For example:

Math.sin(Math.PI); // returns 1.2246467991473532e-16, but should return 0
Math.cos(Math.PI/2); // returns 6.123233995736766e-17, but should return 0
Math.sin(3.14); // returns 0.0015926529164868282, whitch is ok but
Math.sin(3.141592); // returns 6.535897930762419e-7!

I tried this in Mozilla and Chrome and got the same result. It seems the parameter of the trigonometric function is too precise.

Please help!

Nejc Jezersek
  • 621
  • 1
  • 9
  • 19
  • 1
    1.22e-16 is VERY close to zero: it is 0.000000000000000122 to be precise. Since Math.PI is not a perfect representation of PI, as PI is infinite and cannot be contained in any variable, you're always going to get an approximation. – DarkerIvy Dec 18 '17 at 14:41
  • Oh, I didn't see the e-16 so i thought the answer was wrong. Thank you @Darkerlvy – Nejc Jezersek Dec 18 '17 at 14:51
  • No problem. The bottom line is that floating points are very accurate - so accurate that they can even show their own lack of perfection. – DarkerIvy Dec 18 '17 at 15:10
  • To put the error into context, its like measuring the circumference of the earth and getting it wrong by by less than the size of an atom – Blindman67 Jan 07 '18 at 02:33

1 Answers1

1

You could use Number.EPSILON

The Number.EPSILON property represents the difference between 1 and the smallest floating point number greater than 1.

and take the absolute delta of the value and wanted value and check if it is smaller than the Number.EPSILON. If true, then the value's error is smaller than the possible error of floating point arithmetic.

console.log([
    [Math.sin(Math.PI), 0], 
    [Math.cos(Math.PI/2), 0],
    [Math.sin(3.14), 0.0015926529164868282],
    [Math.sin(3.141592), 6.535897930762419e-7]
].map(([a, b]) => Math.abs(a - b) < Number.EPSILON));

Some more to read about the problem with limited digital representation of floating point values:

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392