我们可以依靠op==来对浮点值进行二进制比较吗?

Can we rely on op== to binary-compare floating-point values?

本文关键字:二进制 比较 依靠 op 我们      更新时间:2023-10-16

我们都知道(对吧?!)不应该通过检验相等性来比较浮点值(operator==)。

但是如果我真的想确定两个float, ab是否二进制相等呢?如果它们不允许是NaN(或其他"特殊值"),这是"安全的"吗?我可以依靠operator==以这种方式发挥作用吗?

(假设IEEE-754表示)几乎,但不完全是。如果可以排除nan,则仍然需要处理+0.0-0.0具有不同二进制编码的事实,但比较相等(因为两者完全为零)。

当然,c++不需要IEEE-754。所以严格来说,一切都不确定。

如果您想检查编码是否相等,只需使用memcmp(&a, &b, sizeof a)

可接受的答案忽略了一个非常重要的方面:扩展精度浮点数。CPU可能正在进行比特大小超过存储大小的计算。如果您使用float,则尤其如此,但double和其他浮点类型也可以为真。

为了显示问题,下面的断言实际上可能会失败,这取决于编译的方式和芯片的行为。

  void function( float a )
  {
     float b = a / 0.12345;
     assert( b == (a/0.12345) );
  }

现在,在这个简化的例子中,它很可能总是通过,但在很多情况下它不会通过。只要看看GCC Bug 323,看看有多少缺陷被标记为重复。这种扩展的精度给许多人带来了问题,也可能给您带来问题。

如果你需要一个保证,你需要做的是创建一个比较函数,它接受两个float形参,并保证该函数永远不是内联的(存储float不受扩展精度的限制)。也就是说,必须确保实际存储了这些浮点数。还有一个名为-ffloat-store的GCC选项,我相信它可以强制存储,也许它可以在这里用于您的单个函数。