2012-03-27 64 views
4

爲什麼淨落實Math.Min(浮動,浮動)功能,像這樣:.NET實現:在Math.Min雙轉換(浮動,浮動)

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?特別是如果我想用它來將數值限定爲沒有像0f1f那樣精確的數字。

我應該繼續並實施一個自定義數學庫,此外還需要具有非NaN值才能獲得最佳性能或浪費時間?

public static float Min(float a, float b) 
{ 
    return a < b ? a : b; 
} 
+1

你從哪裏得到.NET Math.Min代碼?你反光了嗎? – Strillo 2012-03-27 08:35:25

+0

是的,我使用了Resharper,它的確如此 – stfx 2012-03-27 08:38:35

+1

我同意@Benny,我認爲性能差異可以忽略不計。 – gideon 2012-03-27 08:40:20

回答

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的這樣做,我會很容易認爲它只是一個錯誤。歡迎來自微軟的源代碼,不僅僅是爲了準確,但評論也很好。

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

+1

其實它確實如此。有[Math.Min(Single,Single)](http://msdn.microsoft.com/en-us/library/070xee48.aspx#Y0) – gideon 2012-03-27 08:39:11

+0

準確Math.Min(Single,Single)在我的情況下,然後 – stfx 2012-03-27 08:41:12

+0

Oooops ..應該讀過兩遍。道歉。 – Strillo 2012-03-27 08:41:48

2

我不能告訴你他們爲什麼選擇投floatdouble的比較,但我懷疑它會造成任何明顯的或對您的程序產生顯着的速度影響。我只是使用內置函數。

+1

我會同意,如果它是一個簡單的Windows應用程序,但由於我正在製作一款遊戲,所以我應該早些提及,當然,我會盡可能快地嘗試,並且這看起來像是一次免費的性能提升;) – stfx 2012-03-27 09:19:06

1

一般而言,您不能認爲Single的執行速度快於Double。 Intel CPU上的浮點寄存器爲80位,CPU上的浮點運算使用該精度執行。在該平臺上,JIT可以生成浮點指令,將參數加載到本機80位寄存器中,唯一的區別是如果寄存器是從32位或64位存儲器位置加載的。也許Math.Min的實現者基於它們的實現來了解JIT編譯器如何生成浮點代碼的複雜知識。

從接受的答案可以看出,問題是基於錯誤的假設(即從SingleDouble)。爲了調查演員是否確實有所作爲,我看了一下Min函數生成的彙編程序,有沒有演員。

這是.NET Framework 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 

還有幾條指令,這些可能會稍微降低功能的性能。

+0

感謝您的研究。就像Hans Passant所說的那樣,這似乎與Resharper有關。如果你使用他發佈的函數,你會得到與.NET框架相同的MSIL代碼(也可能是彙編代碼)。 我非常抱歉浪費你的時間在一個錯誤;( – stfx 2012-03-27 11:10:06