If we execute the following C# code on a console application, we will get a message as The sums are Not equal
.
If we execute it after uncommenting the line System.Console.WriteLine()
, we will get a message as The sums are equal
.
static void Main(string[] args)
{
float f = Sum(0.1f, 0.2f);
float g = Sum(0.1f, 0.2f);
//System.Console.WriteLine("f = " + f + " and g = " + g);
if (f == g)
{
System.Console.WriteLine("The sums are equal");
}
else
{
System.Console.WriteLine("The sums are Not equal");
}
}
static float Sum(float a, float b)
{
System.Console.WriteLine(a + b);
return a + b;
}
What is the actual reason for this behavior?
What is the actual reason for this behaviour?
I can't provide details for exactly what's going on in this specific case, but I understand the general problem, and why using Console.WriteLine
can change things.
As we saw in your previous post, sometimes operations are performed on floating point types at a higher precision than the one specified in the variable type. For local variables, that can include how the value is stored in memory during the execution of a method.
I suspect that in your case:
Sum
method is being inlined (but see later)f
say) is being stored in a high-precision register
g
) is being stored on the stack as a 32-bit value
When you uncomment the Console.WriteLine
statement, I'm guessing that (for whatever reason) forces both variables to be stored in their "proper" 32-bit precision, so they're both being treated the same way.
This hypothesis is all somewhat messed up by the fact that adding
[MethodImpl(MethodImplOptions.NoInlining)]
... does not change the result as far as I can see. I may be doing something else wrong along those lines though.
Really, we should look at the assembly code which is executing - I don't have the time to do that now, unfortunately.
See more on this question at Stackoverflow