Question is not about why 0.1 + 0.9
is not equals 1.0
. Its about different behaviour of a equals.
Can someone explain why examples below works
Looking further into the IL:
summ
is stored in a local of type float32
IL_000d: ldloc.0
IL_000e: ldloc.1
IL_000f: add
IL_0010: stloc.2
the result of q + w
used in q + w == 1.0f
is not; it is used directly in a comparison
IL_0011: ldloc.0
IL_0012: ldloc.1
IL_0013: add
IL_0014: ldc.r4 1.
IL_0019: ceq
Presumably the storage of summ
in a local means it loses enough precision that it becomes equal to 1.0f
.
The problem is due to the fact that the intermediate calculations are being performed in a higher precision, and the rules for when to round back to float
precision are different in each case.
According to 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
is an assignment, and hence is rounded to the nearest float
, which in this case is 1.
q + w == 1.0f
is neither a cast, assignment or function call, so the result of the addition is still an extended precision float, which is close, but not equal, to 1.