如何确定两个双打是否几乎相等

car*_*ysb 1 java math floating-point precision epsilon

我试图找到一些Java代码来确定两个双精度数是否几乎相等。我做了很多Google搜寻,发现了我在这里拼凑而成的点点滴滴。它开始逃脱我的地方是“相对ε”的使用。这种方法似乎是我要寻找的。我不想直接指定epsilon,而是要根据两个参数的大小使用epsilon。这是我编写的代码,我需要对其进行完整性检查。(附言:我知道数学足够危险。)

public class MathUtils
{
    // http://stackoverflow.com/questions/3728246/what-should-be-the-
    // epsilon-value-when-performing-double-value-equal-comparison
    // ULP = Unit in Last Place
    public static double relativeEpsilon( double a, double b )
    {
        return Math.max( Math.ulp( a ), Math.ulp( b ) );
    }

    public static boolean nearlyEqual( double a, double b )
    {
        return nearlyEqual( a, b, relativeEpsilon( a, b ) );
    }

    // http://floating-point-gui.de/errors/comparison/
    public static boolean nearlyEqual( double a, double b, double epsilon )
    {
        final double absA = Math.abs( a );
        final double absB = Math.abs( b );
        final double diff = Math.abs( a - b );

        if( a == b )
        {
            // shortcut, handles infinities
            return true;
        }
        else if( a == 0 || b == 0 || absA + absB < Double.MIN_NORMAL )
        {
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            // NOT SURE HOW RELATIVE EPSILON WORKS IN THIS CASE
            return diff < ( epsilon * Double.MIN_NORMAL );
        }
        else
        {
            // use relative error
            return diff / Math.min( ( absA + absB ), Double.MAX_VALUE ) < epsilon;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Kla*_*aek 7

我会为此使用一个库,我通常使用的是Googles Guava库的DoubleMath。https://google.github.io/guava/releases/19.0/api/docs/com/google/common/math/DoubleMath.html

if (DoubleMath.fuzzyEquals(a, b, epsilon)) { // a and b are equal within the tolerance given } 还有一个模糊比较。

  • @careysb库要求公差的原因是因为正确的公差不仅仅取决于ulp。考虑到到目前为止的计算,它取决于舍入误差的预期范围。 (3认同)