Reputation: 48884
Using Java on a Windows 7 PC (not sure if that matters) and calling Math.cos() on values that should return 0 (like pi/2) instead returns small values, but small values that, unless I'm misunderstanding, are much greater than 1 ulp off from zero.
Math.cos(Math.PI/2) = 6.123233995736766E-17
Math.ulp(Math.cos(Math.PI/2)) = 1.232595164407831E-32
Is this in fact within 1 ulp and I'm simply confused? And would this be an acceptable wrapper method to resolve this minor inaccuracy?
public static double cos(double a){
double temp = Math.abs(a % Math.PI);
if(temp == Math.PI/2)
return 0;
return Math.cos(a);
}
Upvotes: 9
Views: 6302
Reputation: 2231
This is a common error when you are starting out, this link has a very technical discussion of the reasons why. http://docs.sun.com/source/806-3568/ncg_goldberg.html
But in it's simplest form, in the same way that we can't exactly represent 1/3 in the decimal system, there are values that can't be represented exactly in the binary system
Upvotes: 2
Reputation: 8805
You should never use ==
with doubles. You must always do within en error margin. 10-17 is good precision if you ask me. Ulp figure of 10-32 is just precisson of double that is in 10-17 order of magnitude, as 2.220446049250313E-16 is the precision of the number in 100 magnitude.
Upvotes: 7
Reputation: 1504022
Don't forget that Math.PI/2
is an approximation. It's not going to be exactly pi/2, so the result of cos(Math.PI/2)
isn't going to be exactly 0. Math.cos
may be returning a pretty accurate version of the cosine of the exact value returned by calculating Math.PI/2
.
Upvotes: 11