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



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

这两个问题是:

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

  2. 如何调整最大相对和绝对差值,使floatsdoubles正常工作?

检查源代码给了我这个(我删除了范围的实现)

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;

换句话说,如果数字相对相差不超过maxRelDiff的一个因数,或者绝对相差不超过maxAbsDiff

,则函数返回true

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

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

edit:基本上首先决定比较需要有多准确,并在此基础上选择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将优于

虽然我不能回答你原来的问题,但我个人只是使用fabs进行浮点比较:

return fabs(f1 - f2) < 0.10;

相关内容

  • 没有找到相关文章

最新更新