6

All math functions in JavaScript use radians in place of degrees. Yet they are either unequal, or I am way off base.

The conversion from degrees to a radian is:

var rad = angle * Math.PI / 180

A 90 degree angle equals 1.57079633 radian

The cosine of a 90 degree angle equals 0.
The cosine of a 1.57079633 radian equals -3.20510345 × 10-9.

Note that in the Javascript, everything is done in one step to avoid rounding errors:

var cos = Math.cos(angle * Math.PI / 180);

I am obviously missing something obvious here, but boy is it screwing up the code.

SamGoody
  • 11,846
  • 8
  • 70
  • 84

6 Answers6

12

everything is done in one step to avoid rounding errors

How does that avoid rounding errors? It just means that the rounding errors aren't available in a separate variable, that's all.

The true value of pi can't be accurately represented as a floating point number, so the true value of pi / 2 can't either. So you can't give Math.cos the exact value needed to get 0. But hey - 10-9 is a very, very small number. It means that if you were drawing a line 10,000 kilometres long, you'd end up veering 1cm away from the relevant axis.

This is exactly the kind of thing you should expect when dealing with floating point numbers. Don't compare with equality - compare within some tolerance.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • 218k!? Haven't been paying attention, last time I saw you you were on 10k! – Rich Bradshaw Sep 19 '10 at 13:03
  • 2
    This is my first question that Jon Skeet deemed worthy of an answer. – SamGoody Sep 19 '10 at 13:07
  • The tolerance that Jon mentioned is often referred to as epsilon in formal papers – Mr Bell Jul 17 '14 at 14:57
  • @MrBell: Well, I usually use "epsilon" for a smallest representable delta (e.g. http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx) which isn't necessarily the same as the tolerance you want to express. But that may just be me. – Jon Skeet Jul 17 '14 at 21:33
1

There will always be rounding errors. And floating point isn't mathematically accurate anyways, it's only accurate to a certain amount of significant digits.

Change your code so that it doesn't "screw up" when you have errors in the order of 1/1000000000.

Matti Virkkunen
  • 58,926
  • 7
  • 111
  • 152
1

For most of us doing serious sums on computers 0 IS equal to -3.20510345×10^-9 to any reasonable degree of the accuracy that you have a right to expect when working with floating-point numbers. This is a topic that is covered regularly on SO.

High Performance Mark
  • 74,067
  • 7
  • 97
  • 147
1

Yeah, you're just losing data on type conversions here.

90 degress in radians is not equal to exactly 1.57079633. If there were more decimal places, that would convert straight back as expected.

You will always have to be careful with things like this. As mentioned above, the 10^-9 is close enough to zero.

Also taken from MSDN:

In addition, the result of arithmetic and assignment operations with Double values may differ slightly by platform because of the loss of precision of the Double type. For example, the result of assigning a literal Double value may differ in the 32-bit and 64-bit versions of the .NET Framework. The following example illustrates this difference when the literal value -4.42330604244772E-305 and a variable whose value is -4.42330604244772E-305 are assigned to a Double variable. Note that the result of the Parse(String) method in this case does not suffer from a loss of precision.

Jason Plank
  • 2,322
  • 4
  • 29
  • 39
iain
  • 1,500
  • 11
  • 18
0

In computers, π/2 radians cannot exactly equal 90 degrees, because π is an infinitely long number. Therefore, one can't expect perfect presicion with π, unless the computer is ∞-bit.

-3

I just realized:

-3.20510345 × 10-9 is the same as -0.00000000320510345, which is very close to zero.

Google's conversion to radian is rounded, and that rounding causes the err.

My guess is that Javascript, which is notorious for its lack of precision with numbers, also creates an incorrect radian, and therefore its cosign is way off.

Not sure how I would solve this though - rounding is not acceptable, as that wouldn't work for other angles.

SamGoody
  • 11,846
  • 8
  • 70
  • 84
  • 2
    I don't think JS is any more "notorious for its lack of precision with numbers" than anything else that uses floating point arithmetic. Also it would be better if you added this as an edit to your question instead of posting it as an answer. – Matti Virkkunen Sep 19 '10 at 13:07
  • When I started writing it as an answer, there were no other answers. And it does answer the question - if I had added it as an edit, people would complain that there is no valid question. – SamGoody Sep 19 '10 at 13:16