Wei*_* Li 167 c++ floating-point
我知道使用==检查浮点变量的相等性不是一个好方法。但我只想通过以下陈述来了解这一点:
float x = ...
float y = x;
assert(y == x)
Run Code Online (Sandbox Code Playgroud)
既然y是从 复制的x,那么这个断言是真的吗?
cht*_*htz 129
除了assert(NaN==NaN);kmdreko 指出的情况之外,您还可能遇到 x87-math 的情况,即 80 位浮点数临时存储到内存中,然后与仍存储在寄存器中的值进行比较。
可能的最小示例,在编译时使用 gcc9.2 失败-O2 -m32:
#include <cassert>
int main(int argc, char**){
float x = 1.f/(argc+2);
volatile float y = x;
assert(x==y);
}
Run Code Online (Sandbox Code Playgroud)
Godbolt 演示:https ://godbolt.org/z/X-Xt4R
在volatile大概可以忽略,如果你管理,以产生足够的寄存器压力已经y存储并从内存重新加载(但迷惑编译器就够了,不要省略比较全在一起)。
请参阅 GCC 常见问题参考:
kmd*_*eko 119
这不会是如果是真的x是NaN,因为比较的NaN是总是假的(是的,即使NaN == NaN)。对于所有其他情况(正常值、次正常值、无穷大、零),此断言将是正确的。
避免==使用浮点数的建议适用于计算,因为在算术表达式中使用浮点数时无法准确表达许多结果。赋值不是计算,并且没有理由赋值会产生与原始值不同的值。
如果遵循标准,扩展精度评估应该不是问题。从<cfloat>继承自 C [5.2.4.2.2.8](强调我的):
除了赋值和强制转换(删除所有额外的范围和精度),带有浮点操作数的操作的值和受通常算术转换影响的值和浮点常量的值被评估为一种格式,其范围和精度可能大于类型。
然而,正如评论所指出的,某些编译器、构建选项和目标的某些情况可能会使这自相矛盾。
Lig*_*ica 35
是的,y肯定会承担以下价值x:
[expr.ass]/2: 在简单赋值 (=) 中,左操作数引用的对象通过用右操作数的结果替换其值来修改 ([defns.access])。
分配其他值没有余地。
(其他人已经指出,等价比较==仍然会评估falseNaN 值。)
浮点数的常见问题==是很容易没有您认为的价值。在这里,我们知道这两个值,无论它们是什么,都是相同的。
| 归档时间: |
|
| 查看次数: |
12963 次 |
| 最近记录: |