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

发布于 2024-12-24 21:09:30 字数 443 浏览 1 评论 0原文

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

这两个问题是:

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

  2. 如何调整最大相对和绝对差值以便与 floatdouble 正常工作?

At first I thought I could rely on the maximum relative difference only, but I was wrong. For example, if a = 0.0, and b = 0.5, their relative difference is 1.0. In this case approxEquals(lhs, rhs, maxRelDiff, maxAbsDiff) relies on the maximum absolute difference to determine if two floating point numbers are equal.

The two question are:

  1. how do I come up with a new maximum relative and absolute difference pair if the default (1e-2, 1e-5) isn't precise enough? How were 1e-2 and 1e-5 chosen as the default values? For example, if I choose 1e-4 as my maximum relative difference, what is the maximum absolute difference?

  2. How do I adjust the maximum relative and absolute difference values to work properly with floats and doubles?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨的味道风的声音 2024-12-31 21:09:30

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

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

,因此使用 maxRelDiff0.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 且 < code>maxAbsDiff 胜出

checking the source code gives me this (I cut out the implementations for the ranges)

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;
}

this last line is what we'll need to study:

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

in other words the function returns true if the numbers are either relatively different by no more than a factor of maxRelDiff OR absolutely different by no more than maxAbsDiff

so using a maxRelDiff of 0.01 (or 1E-2) compares with an accuracy of 2 (decimal) digits

and using maxAbsDiff different from 0 allows numbers close to 0 to be considered equal even though there relative difference is greater than maxRelDiff

edit: basically first decide how accurate the comparison needs to be and choose your maxRelDiff based on that, then decide at what point should a number be equal to 0

with the examples in the comments:

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

this compares values close to 1 so maxRelDiff trumps here and choosing any maxAbsDiff (lower than maxRelDiff) wont change anything

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

this compares values close to 0 to 0 so the RelDiff (fabs((lhs - rhs) / rhs)) will be 1 and maxAbsDiff trumps

锦爱 2024-12-31 21:09:30

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

return fabs(f1 - f2) < 0.10;

Although I can't answer your original question, I personally just use fabs for floating-point comparisons:

return fabs(f1 - f2) < 0.10;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文