如果我将浮点数复制到另一个变量,它们会相等吗?

新手上路,请多包涵

我知道使用 == 检查浮点变量的相等性不是一个好方法。但我只想通过以下语句知道这一点:

 float x = ...

float y = x;

assert(y == x)

由于 y 是从 x 复制的,那么断言是否正确?

原文由 Wei Li 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 483
2 个回答

除了 kmdreko 指出的 assert(NaN==NaN); 案例外,您还可能遇到 x87-math 的情况,即 80 位浮点数临时存储到内存中,然后与仍存储在寄存器中的值进行比较。

可能的最小示例,当使用 -O2 -m32 编译时使用 gcc9.2 失败:

 #include <cassert>

int main(int argc, char**){
    float x = 1.f/(argc+2);
    volatile float y = x;
    assert(x==y);
}

Godbolt 演示: https ://godbolt.org/z/X-Xt4R

volatile 可能会被省略,如果你设法创建足够的寄存器压力来存储 y 并从内存中重新加载(但足够混淆编译器,不要忽略比较全部 -一起)。

请参阅 GCC 常见问题参考:

原文由 chtz 发布,翻译遵循 CC BY-SA 4.0 许可协议

It won’t be true if x is NaN , since comparisons on NaN are always false (yes, even NaN == NaN ).对于所有其他情况(正常值、次正常值、无穷大、零),此断言将成立。

避免 == 对于浮点数的建议适用于 _计算_,因为浮点数在算术表达式中使用时无法准确表达许多结果。赋值不是计算,没有理由赋值会产生与原始值不同的值。


如果遵循标准,扩展精度评估应该不是问题。从 <cfloat> 继承自 C [5.2.4.2.2.8]( _强调我的_):

除了赋值和强制转换(删除所有额外的范围和精度)之外,具有浮动操作数的操作的值和经过通常算术转换的值以及浮动常量的值被评估为范围和精度可能大于要求的格式类型。

然而,正如评论所指出的那样,某些编译器、构建选项和目标的 情况可能 会使这自相矛盾地成为错误。

原文由 kmdreko 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题