proxEqual()的正确用法是什么?

时间:2012-01-02 01:18:00

标签: floating-point d phobos

起初我以为我只能依靠最大相对差异,但我错了。例如,如果a = 0.0b = 0.5,则它们的相对差异为1.0。在这种情况下,approxEquals(lhs, rhs, maxRelDiff, maxAbsDiff)依赖于最大绝对差值来确定两个浮点数是否相等。

这两个问题是:

  1. 如果默认值(1e-2,1e-5)不够精确,我怎么能想出一个新的最大相对和绝对差值对?如何选择1e-21e-5作为默认值?例如,如果我选择1e-4作为我的最大相对差异,那么最大绝对差异是多少?

  2. 如何调整最大相对和绝对差值,使其与floatsdoubles一起正常使用?

2 个答案:

答案 0 :(得分:1)

检查source code给了我这个(我删除了范围的实现)

bool approxEqual(T, U, V)(T lhs, U rhs, V maxRelDiff, V maxAbsDiff = 1e-5)
{   

    if (rhs == 0)
    {
        return fabs(lhs) <= maxAbsDiff;
    }
    static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity)))
    {
        if (lhs == lhs.infinity && rhs == rhs.infinity ||
            lhs == -lhs.infinity && rhs == -rhs.infinity) return true;
    }
    return fabs((lhs - rhs) / rhs) <= maxRelDiff
        || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
}

这最后一行是我们需要研究的内容:

return fabs((lhs - rhs) / rhs) <= maxRelDiff
        || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;

换句话说,如果数字相对不同,则函数返回true,不超过maxRelDiff绝对的因数不超过maxAbsDiff

所以使用maxRelDiff 0.01(或1E-2)与2(十进制)数字的准确度进行比较

并使用不同于0的maxAbsDiff允许接近0的数字被认为是相等的,即使相对差异大于maxRelDiff

编辑:基本上首先要确定比较需要多准确,然后根据它选择maxRelDiff,然后决定数字应该在什么时候等于0

注释中的示例:

approxEqual(1+1e-10, 1.0, 1e-10, 1e-30) 
approxEqual(1+1e-10, 1.0, 1e-9, 1e-30)

这会比较接近1的值,因此maxRelDiff胜过此处并选择任何maxAbsDiff(低于maxRelDiff)不会改变任何内容

approxEqual(0, 1e-10, 1e-10, 1e-30) 
approxEqual(0, 1e-9, 1e-9, 1e-30)

这会比较接近0到0的值,因此RelDiff(fabs((lhs - rhs) / rhs))将为1而maxAbsDiff胜过

答案 1 :(得分:0)

虽然我无法回答您的原始问题,但我个人只是使​​用fabs进行浮点比较:

return fabs(f1 - f2) < 0.10;