浮点等号的意外结果
本文关键字:意外 结果 | 更新日期: 2023-09-27 17:49:24
问题不是关于为什么0.1 + 0.9
不等于1.0
。这是关于等号的不同行为。
谁能解释一下为什么下面的例子不同?
float q = 0.1f;
float w = 0.9f;
float summ = q + w;
q + w == 1.0f; // False
summ == 1.0f; // True
为什么操作符==
的工作方式不同?
问题是由于中间计算正在以更高的精度执行,并且何时舍入到float
精度的规则在每种情况下都是不同的。
根据文档
默认情况下,在x86架构的代码中,编译器使用协处理器的80位寄存器来保存浮点计算的中间结果。
…在赋值和强制类型转换以及将形参传递给函数时,编译器对
float
类型的变量执行舍入到正确的精度"
float summ = q + w
是一个赋值,因此被四舍五入到最接近的float
,在本例中为1。
q + w == 1.0f
既不是强制转换、赋值也不是函数调用,所以加法的结果仍然是一个扩展的精度浮点数,它接近但不等于1。
进一步了解IL:
summ
存储在float32
IL_000d: ldloc.0
IL_000e: ldloc.1
IL_000f: add
IL_0010: stloc.2
q + w
在q + w == 1.0f
中使用的结果是not;它直接用于比较
IL_0011: ldloc.0
IL_0012: ldloc.1
IL_0013: add
IL_0014: ldc.r4 1.
IL_0019: ceq
假定summ
在本地存储意味着它失去了足够的精度,因此它等于1.0f
。