在Windows 7 PC上使用Java(不确定是否重要)并在应该返回0的值(如pi / 2)上调用Math.cos()而不是返回小值,但是小值,除非我是误解,从零开始大大超过1 ulp。
Math.cos(Math.PI/2) = 6.123233995736766E-17
Math.ulp(Math.cos(Math.PI/2)) = 1.232595164407831E-32
这实际上是在1 ulp内吗?我只是感到困惑?这是否是一种可以接受的解决这种轻微不准确的包装方法?
public static double cos(double a){
double temp = Math.abs(a % Math.PI);
if(temp == Math.PI/2)
return 0;
return Math.cos(a);
}
答案 0 :(得分:11)
不要忘记Math.PI/2
是近似值。它不会完全 pi / 2,因此cos(Math.PI/2)
的结果不会完全 0. Math.cos
可能会返回通过计算Math.PI/2
返回的精确值的余弦的精确版本。
答案 1 :(得分:7)
你永远不应该使用==
双打。您必须始终在误差范围内。如果你问我,10 -17 是很好的精确度。 10 -32 的Ulp数字只是10 -17 数量级的倍数的preisson,因为2.220446049250313E-16是10 0 幅度。
答案 2 :(得分:2)
这是一个常见的错误,当你开始时,这个链接有一个非常技术性的讨论原因。 http://docs.sun.com/source/806-3568/ncg_goldberg.html
但是它是最简单的形式,就像我们不能在十进制系统中完全代表1/3一样,有些值无法在二进制系统中准确表示