不幸的是,你选择了一个不好的例子。x86 JIT 编译器不会内联返回浮点数的方法。不是 100% 确定为什么,我认为它确实可以避免在 FPU 中将浮点数转换为 80 位浮点值时出现问题。内部精度为 80 位,但是当 80 位值被刷新回内存时,这些额外的位被截断回 32 位值。将 FPU 中的值保持太久可防止发生这种截断并更改计算结果。
如果将 float 替换为 double 并编译此代码:
static void Main(string[] args) {
Console.WriteLine(Cube(2.0));
}
然后在启用 JIT 优化器时生成此机器代码:
00000000 push ebp ; setup stack frame
00000001 mov ebp,esp
00000003 call 6DA2BEF0 ; Console.get_Out()
00000008 fld qword ptr ds:[010914B0h] ; ST0 = 8.0
0000000e sub esp,8 ; setup argument for WriteLine
00000011 fstp qword ptr [esp]
00000014 mov ecx,eax ; call Console.Out.WriteLine
00000016 mov eax,dword ptr [ecx]
00000018 call dword ptr [eax+000000D0h]
0000001e pop ebp ; done
0000001f ret
它不仅内联了函数,而且能够在编译时评估表达式。并通过调用 Console.WriteLine(8.0) 直接传递结果。很不错吧?
使用双精度,而不是浮点数。