It's not related to scope. It's the combination of the stack dynamics and floating point handling. Some knowledge of compilers will help make this counterintuitive behavior clear.
When the Console.WriteLine
is commented, the values f
and g
are on the evaluation stack and stay there until after you've passed the equality test in your Main method.
When Console.Writeline
is not commented, the values f
and g
are moved from the evaluation stack to the call stack at the moment of the invocation, to be restored to the evaluation stack when Console.WriteLine
returns. And your comparison if (f == g)
is done afterwards. Some rounding can occur during this storing of values to the call stack and some information can be lost.
In the scenario where you do invoke Console.WriteLine
, the f
and the g
in the comparison test are not the same values. They've been copied and restored to a format that has different rules on precision and rounding, by the virtual machine.
In your particular code, when the invocation of Console.WriteLine
is commented, the evaluation stack is never stored to the call stack and no rounding occurs. Because it is permitted for implementations of the platform to provide improved precision on the evaluation stack, this discrepancy can arise.
EDIT What we're hitting in this case is allowed by the CLI specification. In section I.12.1.3 it reads:
Storage locations for floating-point numbers (statics, array elements,
and fields of classes) are of fixed size. The supported storage sizes
are float32 and float64. Everywhere else (on the evaluation stack, as
arguments, as return types, and as local variables) floating-point
numbers are represented using an internal floating-point type. In each
such instance, the nominal type of the variable or expression is
either float32or float64, but its value can be represented internally
with additional range and/or precision. The size of the internal
floating-point representation is implementation-dependent, can vary,
and shall have precision at least as great as that of the variable or
expression being represented.
The keywords from this quote are "implementation-dependent" and "can vary". In the OP's case, we see his implementation does indeed vary.
Non-strictfp floating point arithmetic in the Java platform also has a related issue, for more info check also my answer to Will floating point operations on the JVM give the same results on all platforms?
csc /o+ /debug- /platform:x86 Test.cs
. It may well still vary by subtle things like CLR version etc though. – HazelMath.Abs(a - b) < epsilon
, where epsilon is required precision. True then a equal b, with reqired precision. – Docilafloat
values numbers with accuracy beyond that which would be obtained if the intermediate results were rounded tofloat
, and other times when one needs the exact result that would be achieved when results are rounded. – Winnifredwinning