浮点等于的意外结果

时间:2015-05-15 07:22:17

标签: c# floating-point

问题不在于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

为什么运算符==的工作方式不同?

2 个答案:

答案 0 :(得分:2)

进一步了解IL:

summ存储在float32

类型的本地
IL_000d:  ldloc.0
IL_000e:  ldloc.1
IL_000f:  add
IL_0010:  stloc.2

q + w中使用q + w == 1.0f的结果不是;它直接用于比较

IL_0011:  ldloc.0
IL_0012:  ldloc.1
IL_0013:  add
IL_0014:  ldc.r4     1.
IL_0019:  ceq

据推测,summ存储在本地意味着它会失去足够的精度,使其等于1.0f

答案 1 :(得分:2)

问题是由于中间计算以更高的精度执行,并且在每种情况下回退到float精度的时间规则都不同。

根据the docs

  

默认情况下,在x86架构的代码中,编译器使用协处理器的80位寄存器来保存浮点计算的中间结果。

     

...编译器对类型float的变量执行舍入,以便为赋值和强制转换以及参数传递给函数时的正确精度“

float summ = q + w是一项作业,因此四舍五入到最近的float,在这种情况下为1。

q + w == 1.0f既不是强制转换,也不是函数调用,因此加法的结果仍然是一个扩展的精度浮点数,它接近但不等于1。