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

时间:2011-11-08 01:15:12

标签: c++ floating-point

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

但是,如果我确实想确定两个float ab 二进制相等,该怎么办?如果他们不被允许为NaN(或其他“特殊价值”),这是“安全的”吗?我可以依靠operator==以这种方式运作吗?

3 个答案:

答案 0 :(得分:20)

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

当然,C ++不需要IEEE-754。所以严格来说,所有赌注都已关闭。

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

答案 1 :(得分:5)

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

为了显示问题,以下断言实际上可能会失败,具体取决于编译的完成方式以及芯片的行为方式。

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

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

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

答案 2 :(得分:-4)

要确保浮点值不是NaN,您可以将其与自身进行比较:

double foo;
// do something with foo
if (foo != foo) {
    std::cout << "Halp! Foo is NaN!";
}

我很确定这是IEEE-754标准所保证的。