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

Lig*_*ica 14 c++ floating-point

我们都知道(对吗?!),不应该通过测试equality(operator==)来比较浮点值.

但是,如果我真的想确定两个是否float小号ab二进制的平等?如果他们不被允许为NaN(或其他"特殊价值"),这是"安全的"吗?我可以依靠operator==这种方式运作吗?

Ste*_*non 20

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

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

如果要检查(in)编码的相等性,请使用memcmp(&a, &b, sizeof a).

  • @ edA-qamort-ora-y:是的,标准中的"as-if"规则强制行为与两个值都存储时无法区分,因为需要存储一个值才能传递其地址一个功能.(它们实际上不需要存储;例如,它们可以四舍五入到它们的实际精度,然后复制到通用寄存器中并作为整数编码进行比较). (2认同)

edA*_*a-y 5

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

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

  void function( float a )
  {
     float b = a / 0.12345;
     assert( b == (a/0.12345) );
  }
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这真的回答了这个问题吗?如果`a`和`b`甚至没有相同的位数(由于扩展的浮点精度),那么它们是否是二进制相同的问题有点无意义. (4认同)