There is a strange behavior I cannot understand. Agreed that float point number are approximations, so even operations that are obviously returning a number without decimal
I looked to see if this was the compiler doing the math, but it behaves this way even if you force it out:
static void Main()
{
int i = (int)(GetF() * GetI()); // 19594
float f = GetF() * GetI();
int j = (int)f; // 19595
}
[MethodImpl(MethodImplOptions.NoInlining)]
static int GetI() { return 100; }
[MethodImpl(MethodImplOptions.NoInlining)]
static float GetF() { return 195.95F; }
It looks like the difference is whether it stays in the registers (wider than normal r4) or is forced to a float
variable:
L_0001: call float32 Program::GetF()
L_0006: call int32 Program::GetI()
L_000b: conv.r4
L_000c: mul
L_000d: conv.i4
L_000e: stloc.0
vs
L_000f: call float32 Program::GetF()
L_0014: call int32 Program::GetI()
L_0019: conv.r4
L_001a: mul
L_001b: stloc.1
L_001c: ldloc.1
L_001d: conv.i4
L_001e: stloc.2
The only difference is the stloc.1
/ ldloc.1
.
This is supported by the fact that if you do an optimised build (which will remove the local variable) I get the same answer (19594) for both.