当您直接操作时,允许以更高的精度执行操作,并且允许多个操作继续以更高的精度。
来自 C# 5 规范的第 4.1.6 节:
浮点运算可以以比运算结果类型更高的精度执行。例如,一些硬件架构支持比 double 类型具有更大范围和精度的“扩展”或“long double”浮点类型,并使用这种更高精度类型隐式执行所有浮点运算。只有在性能成本过高的情况下,才能使此类硬件架构以较低的精度执行浮点运算,而不是要求实现同时丧失性能和精度,C# 允许将更高精度的类型用于所有浮点运算.除了提供更精确的结果之外,这很少有任何可衡量的影响。然而,在 x * y / z 形式的表达式中,乘法产生的结果超出了双精度范围,但随后的除法将临时结果带回双精度范围,事实上,表达式在更高的范围内计算范围格式可能会导致生成有限结果而不是无穷大。
我希望在某些优化方案中,如果 JIT 决定它永远不需要将值作为 float ,那么额外局部变量的答案甚至可能是“错误的”。 (我已经看到仅添加日志记录会改变此处行为的情况......)
在这种情况下,我认为除法实际上是使用 64 位算术执行的,然后将 从 double 直接转换为 int,而不是先通过 float。
这里有一些代码来证明这一点,使用DoubleConverter 类,它可以让您找到浮点数的精确十进制表示:
using System;
class Test
{
static void Main()
{
float a = 10f;
float b = 0.1f;
float c = a / b;
double d = (double) a / (double) b;
float e = (float) d;
Console.WriteLine(DoubleConverter.ToExactString(c));
Console.WriteLine(DoubleConverter.ToExactString(d));
Console.WriteLine(DoubleConverter.ToExactString(e));
Console.WriteLine((int) c);
Console.WriteLine((int) d);
Console.WriteLine((int) e);
}
}
输出:
100
99.999998509883909036943805404007434844970703125
100
100
99
100
请注意,该操作可能不仅仅以 64 位执行 - 它可能以更高的精度执行,例如80 位。
这只是浮点二进制运算的乐趣之一 - 也是为什么您需要非常小心您正在做的事情的一个例子。
请注意,0.1f 正好 0.100000001490116119384765625 - 所以大于 0.1。鉴于它大于 0.1,我 预计 10/b 会略小于 100 - 如果“略少”是可表示的,那么截断结果自然会导致 99。