为什么.Net实现了Math.Min(float,float)函数,如下所示:
public static float Min(float val1, float val2)
{
if ((double) val1 < (double) val2 || float.IsNaN(val1))
return val1;
else
return val2;
}
虽然我可以看到使用IsNaN但我不明白为什么在比较值时它们会转换为double。这不比简单地写val < val 2
慢吗?特别是如果我想用它来将数字钳位到数字而不太精确,例如0f
或1f
。
我是否应该继续实施一个自定义数学库,另外还需要具有非NaN值以获得最佳性能,还是浪费时间?
public static float Min(float a, float b)
{
return a < b ? a : b;
}
答案 0 :(得分:5)
是的,我使用了Resharper,它正是这样做的
这就是问题所在,它会使代码失误。源代码可从Reference Source获得,如下所示:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static float Min(float val1, float val2) {
if (val1 < val2)
return val1;
if (Single.IsNaN(val1))
return val1;
return val2;
}
很难猜出为什么Resharper这样做,我很容易认为它只是一个bug。支持Microsoft提供的源代码,不仅仅是为了准确,但评论也很好。
答案 1 :(得分:2)
我无法告诉你为什么他们选择将float
投射到double
进行比较,但我怀疑它会对你的程序产生明显或显着的速度影响。我只是使用内置函数。
答案 2 :(得分:1)
没有Math.Min(float,float)这样的东西。 .NET仅包含Min(double,double)的定义。 查看MSDN:http://msdn.microsoft.com/en-us/library/system.math.min(v=vs.100).aspx
编辑:有,谢谢@gideon http://msdn.microsoft.com/en-us/library/070xee48.aspx
答案 3 :(得分:1)
通常,您不能认为Single
的执行速度比Double
快。 Intel CPU上的浮点寄存器为80位,CPU上的浮点运算使用该精度执行。在该平台上,JIT可以生成浮点指令,将参数加载到本机80位寄存器中,唯一的区别在于寄存器是从32位还是64位存储器位置加载的。也许Math.Min
的实现者基于JIT编译器如何生成浮点代码的复杂知识来实现它们。
从接受的答案可以看出,问题是基于错误的假设(从Single
到Double
的演员表)。为了调查转换是否确实有所不同,我查看了Min
函数生成的汇编程序,有或没有强制转换。
这是我在调试器中看到的.NET框架Math.Min(Single, Single)
:
00000000 push ebp 00000001 mov ebp,esp 00000003 fld dword ptr [ebp+0Ch] 00000006 fld dword ptr [ebp+8] 00000009 fxch st(1) 0000000b fcomi st,st(1) 0000000d jp 00000015 0000000f jae 00000015 00000011 fstp st(1) 00000013 jmp 00000022 00000015 fcomi st,st(0) 00000017 jp 0000001B 00000019 je 00000026 0000001b mov eax,1 00000020 jmp 00000028 00000022 pop ebp 00000023 ret 8 00000026 xor eax,eax 00000028 test eax,eax 0000002a je 00000030 0000002c fstp st(1) 0000002e jmp 00000036 00000030 fstp st(0) 00000032 pop ebp 00000033 ret 8 00000036 pop ebp 00000037 ret 8
以下是使用强制转换为Double
的函数的程序集,就像问题一样:
00000000 push ebp 00000001 mov ebp,esp 00000003 sub esp,8 00000006 fld dword ptr [ebp+0Ch] 00000009 fld dword ptr [ebp+8] 0000000c fld st(1) 0000000e fstp qword ptr [ebp-8] 00000011 fld qword ptr [ebp-8] 00000014 fld st(1) 00000016 fstp qword ptr [ebp-8] 00000019 fld qword ptr [ebp-8] 0000001c fcomip st,st(1) 0000001e fstp st(0) 00000020 jp 00000028 00000022 jbe 00000028 00000024 fstp st(0) 00000026 jmp 00000043 00000028 fxch st(1) 0000002a fcomi st,st(0) 0000002c jp 00000030 0000002e je 00000037 00000030 mov eax,1 00000035 jmp 00000039 00000037 xor eax,eax 00000039 test eax,eax 0000003b jne 00000041 0000003d fstp st(0) 0000003f jmp 00000049 00000041 fstp st(1) 00000043 mov esp,ebp 00000045 pop ebp 00000046 ret 8 00000049 mov esp,ebp 0000004b pop ebp 0000004c ret 8
还有一些说明,这些可能会略微降低功能的性能。