9

在 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);
}
4

3 回答 3

11

不要忘记这Math.PI/2是一个近似值。它不会完全是pi/2,因此 的结果cos(Math.PI/2)不会完全是0。Math.cos可能会返回相当准确的余弦版本,该版本是由计算返回的确切值的余弦值Math.PI/2

于 2010-02-10T09:36:17.920 回答
7

你永远不应该使用==双打。您必须始终在误差范围内进行。如果你问我,10 -17是很好的精度。Ulp 数字 10 -32只是 10 -17数量级的 double 精度,因为 2.220446049250313E-16 是 10 0数量级的数字精度。

于 2010-02-10T09:46:01.167 回答
2

这是您刚开始时的常见错误,此链接对原因进行了非常技术性的讨论。 http://docs.sun.com/source/806-3568/ncg_goldberg.html

但以最简单的形式,就像我们不能在十进制系统中准确表示 1/3 一样,有些值在二进制系统中也不能准确表示

于 2010-02-10T09:51:54.090 回答