【问题标题】:Is it correct to compare two rounded floating point numbers using the == operator?使用 == 运算符比较两个舍入浮点数是否正确?
【发布时间】:2008-10-25 13:54:35
【问题描述】:

或者有没有可能操作会失败?

谢谢。

我选择了错误的术语,我真正的意思是四舍五入到 0,而不是截断。

关键是,我需要比较两个双精度的整数部分,我只是将它们转换为 int,然后使用 ==,但是,正如有人在我之前的一个问题中指出的那样,这可能会引发溢出如果双精度不能放入整数,则异常。

所以问题是'使用 == 运算符比较两个先前舍入为 0 的双精度值是否正确,或者我应该坚持转换为 int 方法并捕获可能的异常?

【问题讨论】:

标签: .net floating-point compare rounding


【解决方案1】:

Here's the updated site 讨论了几种比较浮点数的方法的优缺点。 (您仍然可以查看old site here。)

我要采用的方法是“相对误差”方法。找出两个数字之间的差异,将其转换为数字的百分比,如果该百分比足够小,那么您就得到了相等。

【讨论】:

    【解决方案2】:

    更糟糕的是,有时,即使是完全相同的数字,它也会失败。这是因为一些编译器或处理器将在 CPU 寄存器中使用比在内存中更多的精度位(例如,MSVC 有 3 种不同的浮点行为选项)。因此,最近计算的值可能不会截断这些位,并且看起来不相等。永远不要在浮点数上使用 ==。

    【讨论】:

      【解决方案3】:

      由于浮点表示的正常问题,它仍然可能失败。与其截断它们,不如使用表示等效精度的增量。

      如果您有两个通常认为相同的浮点数,它可能会失败,

      10.19999999

      10.20000001

      但是当你截断它们时,它们会给出不同的结果。

      10.19

      10.20

      然而,如果我使用 0.001 的 delta 来比较差异,我会发现这两个值实际上是相同的。

      【讨论】:

        【解决方案4】:

        == 与浮点一起使用是不正确的。

        在浮点上下文中“截断”是什么意思?你在调用什么特定的库函数?结果是什么?是什么让您相信“截断”值比非截断值更具可比性?

        浮点是十进制值的近似值。浮点数只能精确表示二的幂。无论您执行何种浮点运算,所有其他值都会出现一些错误。

        但是,如果您转换为整数,则可以使用 ==

        【讨论】:

        • 永远不要说“从不”。如果你有一个相对计算的计算涉及到在 IEEE 754 中完全可以表示的数字,那么使用 == 是可以的,但是这种情况很少见。
        • @Adam Rosenfield:“完全可表示”条款将是无关紧要的。如果您知道表达式的结果,则只需使用答案。如果你写了一个程序,你不知道结果,也不知道它是否完全可表示。永远不要使用 ==。
        • 如果您正在为一些浮点数学运算编写单元测试怎么办?如果您确切知道答案应该是什么,那么在这种情况下您应该使用 ==。永远不要说“从不”。
        • @Adam Rosenfield:还是不同意。那是单元测试,而不是应用程序编程。单元测试可能很脆弱,并且取决于特定的库版本和硬件。这种例外是如此罕见,如此微小且如此容易出错,以至于我坚持我疯狂的绝对主义。永远不要使用 ==。
        • 我今天才使用“== 0”。它足够安全。如果没有重叠,则计算两个矩形之间重叠区域的方法返回 0。我当然可以测试结果是否为零。
        【解决方案5】:
        【解决方案6】:

        如果您的绝对值小于 2^23(单人)或 2^52(双人),您可以使用 round() 然后进行比较。 较大的值无法精确存储,这适用于 N == N+1 的情况。

        【讨论】:

        • 这需要四舍五入,而不是截断。当然,我不完全确定 OP 的截断(ceil()?)是什么意思,但大概如果他的意思是四舍五入,他会这么说......
        • Ceil 在处理负数时与 Trunc 不同。我的观点是,从等式中取出舍入/截断/天花板/地板,您可以安全地进行比较。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-24
        • 1970-01-01
        • 2014-09-13
        • 2012-12-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多