Java Math.cos(Math.toRadians()) returns wei

2019-01-12 04:55发布

问题:

I've got a little Problem with the Math.cos() method. I know, I have to convert the angle to Radians before using Math.cos(). But if I just do:

System.out.println(Math.cos(Math.toRadians(90));

It outputs: 6.123233995736766E-17

Math.sin() is working well.

回答1:

From trigonometry:

sin x ~= x, for small values of x
sin x = cos x+pi/2

Because pi/2 can't be represented exactly in IEEE-754 Floating point, it means, that it must be off by some value x, i.e it is represented by pi/2 +- x, where x < the least significant bit in the floating point system. Which in this case is 2^-53 = 1.1102e-16.

In this particular case x ~= 6.123233995736766E-17, which is about 55% of the maximum error. So, it's a rather good result...



回答2:

See the Javadoc. "The conversion from degrees to radians is generally inexact."



回答3:

The value is very close to the correct result. It seems like a loss of precision in the floating point operations of transforming degrees to radians.



回答4:

Standing temporarily on a soapbox, I think people are confused about the concepts of accuracy versus precision. Is this an issue as some have said? Is it a problem? A bug? Or is it an expected behavior of floating point arithmetic?

90 degrees is a number that is representable perfectly as an integer, even though a double. But pi/2 radians is a real number that is not represented exactly, so that representation will be slightly inaccurate. The loss is in accuracy. The fact is, this is expected behavior. We should never trust the least significant bits of a result.

Next, when we compute the value of a trigonometric function, there MAY be an additional loss of accuracy. We don't get exactly the result that we know to be true in a symbolic sense. Thus sin(pi/3) may not be exactly sqrt(3)/2, but then we can't represent sqrt(3)/2 exactly anyway. All of this is expected, and is behavior that should be dealt with by good code, not trusting the LSBs of those numbers.