测试两个浮点数的相等性:现实示例

计算科学 浮点
2021-12-11 10:07:08

在编程中测试两个浮点数的相等性通常什么时候有意义?

IE

a == b 

其中 a & b 都是浮点数。

我的天真印象是,人们总是会根据一些公差 epsilon 来测试差异。

我错了吗?在某些情况下测试浮点数的相等性是否有意义?

有来自野外的例子吗?即来自真正的代码库或 git 等应用程序。

PS。我隐含地假设在某些情况下在浮点数上使用相等运算符确实有意义;否则为什么大多数编程语言会允许它。

4个回答

我的天真印象是,人们总是会根据一些公差 epsilon 来测试差异。

这个想法的一个不简单的实现可能应该利用相等比较运算符来处理IEEE 754标准考虑的重要特殊情况(无穷大、非规范化数字......)。

看看我应该如何进行浮点比较?

...

if (a == b)  // shortcut, handles infinities
  return true;

if (a == 0 || b == 0 || diff < Float.MIN_NORMAL) {
  // a or b is zero or both are extremely close to it
  // relative error is less meaningful here

...


有时确实有一个答案是正确的,而您想要完全相等。测试实现的正确性是一个很好的例子(即只有 40 亿个浮点数——所以测试它们!)。

可以的一个明显示例==是何时ab是相同的数字a=c; b=c,例如,检查ab是否以相同的方式初始化。当然,|a-b| < epsilon也可以在这里工作。唯一的问题是,有多小epsilon

此外,a == b会编译成一条指令,而|a-b| < epsilon需要相当多的指令。

一个极端的例子:IBM 是第一家使用融合乘加指令构建处理器的公司。使用该指令,他们创建了一种非常快速的方法来根据 IEEE-754 标准计算平方根。对于单个输入值 1 ≤ x < 4,此方法失败:如果 x 是可表示为小于 4 的浮点数的最大数字,则结果将被错误地舍入。

所以在他们实现的某个地方,他们检查 x 是否等于那个特定的值。他们想要认识到这种价值,而不是其他任何价值。

我的天真印象是,人们总是会根据一些公差 epsilon 来测试差异。我错了吗?在某些情况下测试浮点数的相等性是否有意义?

没有独特的食谱。本文中,有一个详尽的处理方法,您可以在其中找到包含技术和代码的完整答案。

总结起来主要有3种情况:

  • 与零比较
  • 与非零比较
  • 比较两个任意数

在某些情况下,您使用与容差进行比较的想法很好,但还有一种基于 Unit in the last place ( ULP ) 的技术,在文章中进行了描述

我隐含地假设在某些情况下在浮点数上使用相等运算符确实有意义;否则为什么大多数编程语言会允许它。

如上所述,在某些情况下您可以使用它,但请注意。例如 gcc 编译器有一个警告:

warning: comparing floating point with == or != is unsafe

更新

我在这个论点之上添加了一些注意事项,它们与案例并不严格相关a == b

表达平等

考虑案例:

a + b == c 

a b c花车。这就是我们正在编码的内容,但从数学的角度来看,我们正在做的事情更加迂腐:

ab==cfl(fl(a)+fl(b))==fl(c)
在哪里

  • 机加
  • fl(x)是数字的浮点表示x,即真机号。

通过这个操作,我们引入了一个可能的估计误差(给出界限):

|aa+b|erra+|ba+b|errb
在哪里
errx=|xfl(x)||x|

所以在这种情况下使用==起来就更加微妙了。

移植到不同的环境

当我们将代码移植到不同的环境(不同的机器)中时,我们可以获得一些不同的结果(例如尝试思考单元测试)。在使用的情况下==也是微妙的。