一尘不染

C#的浮点比较功能

c#

有人可以指向(或显示)C#中一些好的通用浮点比较函数来比较浮点值吗?我想实施的功能IsEqualIsGreater一个IsLess。我也只在乎双打而不在乎浮动。


阅读 427

收藏
2020-05-19

共1个答案

一尘不染

编写有用的通用浮点IsEqual非常非常困难,即使不是完全不可能的。您当前的代码将因严重失败a==0。在这种情况下,该方法的行为确实是一个定义问题,并且可以说,最好针对特定领域用例量身定制代码。

对于这种事情,您 确实非常需要 一个好的测试套件。这就是我在《浮点指南》中所做的事情,这就是我最后想出的(Java代码,应该足够容易翻译):

public static boolean nearlyEqual(float a, float b, float epsilon) {
    final float absA = Math.abs(a);
    final float absB = Math.abs(b);
    final float diff = Math.abs(a - b);

    if (a == b) { // shortcut, handles infinities
        return true;
    } else if (a == 0 || b == 0 || absA + absB < Float.MIN_NORMAL) {
        // a or b is zero or both are extremely close to it
        // relative error is less meaningful here
        return diff < (epsilon * Float.MIN_NORMAL);
    } else { // use relative error
        return diff / (absA + absB) < epsilon;
    }
}

您还可以在网站上找到测试套件

附录: c#中相同的代码用于双打(按问题要求)

public static bool NearlyEqual(double a, double b, double epsilon)
{
    const double MinNormal = 2.2250738585072014E-308d;
    double absA = Math.Abs(a);
    double absB = Math.Abs(b);
    double diff = Math.Abs(a - b);

    if (a.Equals(b))
    { // shortcut, handles infinities
        return true;
    } 
    else if (a == 0 || b == 0 || absA + absB < MinNormal) 
    {
        // a or b is zero or both are extremely close to it
        // relative error is less meaningful here
        return diff < (epsilon * MinNormal);
    }
    else
    { // use relative error
        return diff / (absA + absB) < epsilon;
    }
}
2020-05-19