浮点等于的意外结果

Unexpected results for floating point equals

问题不是关于为什么 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

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

深入了解 IL:

summ 存储在 float32

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

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

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

据推测,summ 在本地的存储意味着它失去了足够的精度,以至于它变得等于 1.0f

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

根据the docs

By default, in code for x86 architectures the compiler uses the coprocessor's 80-bit registers to hold the intermediate results of floating-point calculations.

... the compiler performs rounding on variables of type float to the correct precision for assignments and casts and when parameters are passed to a function"

float summ = q + w 是一项赋值,因此四舍五入到最接近的 float,在本例中为 1。

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