3 回答

TA貢獻1858條經(jīng)驗 獲得超8個贊
MethodImplOptions.InternalCall
這意味著該方法實際上是在用C ++編寫的CLR中實現(xiàn)的。即時編譯器使用內(nèi)部實現(xiàn)的方法查詢表,并直接編譯對C ++函數(shù)的調(diào)用。
查看代碼需要CLR的源代碼。您可以從SSCLI20發(fā)行版中獲得。它是圍繞.NET 2.0時間框架編寫的,我發(fā)現(xiàn)了低級實現(xiàn),Math.Pow()
對于CLR的后續(xù)版本來說仍然很準確。
查找表位于clr / src / vm / ecall.cpp中。Math.Pow()
與此相關(guān)的部分如下所示:
FCFuncStart(gMathFuncs) FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin) FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos) FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt) FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round) FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs) FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs) FCFuncElement("Exp", COMDouble::Exp) FCFuncElement("Pow", COMDouble::Pow) // etc.. FCFuncEnd()
搜索“COMDouble”會將您帶到clr / src / classlibnative / float / comfloat.cpp。我會把你的代碼留給你,只是看看你自己。它基本上檢查了極端情況,然后調(diào)用CRT的版本pow()
。
唯一有趣的其他實現(xiàn)細節(jié)是表中的FCIntrinsic宏。這暗示了抖動可以將函數(shù)實現(xiàn)為內(nèi)在函數(shù)。換句話說,用浮點機器代碼指令替換函數(shù)調(diào)用。事實并非如此Pow()
,沒有FPU指令。但肯定是其他簡單的操作。值得注意的是,這可以使C#中的浮點數(shù)學運算速度明顯快于C ++中的相同代碼,請查看此答案。
順便說一句,如果你有完整版本的Visual Studio vc / crt / src目錄,也可以使用CRT的源代碼。pow()
不過,你會碰壁,微軟從英特爾那里購買了這些代碼。不太可能比英特爾工程師做得更好。雖然我的高中書的身份是我嘗試時的兩倍:
public static double FasterPow(double x, double y) { return Math.Exp(y * Math.Log(x)); }
但不是真正的替代品,因為它累積了來自3個浮點運算的錯誤,并且沒有處理Pow()所具有的怪異域問題。像0 ^ 0和-Infinity提升到任何功率。

TA貢獻1804條經(jīng)驗 獲得超7個贊
Hans Passant的答案很棒,但我想補充一點,如果b
是一個整數(shù),那么a^b
可以通過二進制分解非常有效地計算。這是Henry Warren的Hacker's Delight的修改版本:
public static int iexp(int a, uint b) { int y = 1; while(true) { if ((b & 1) != 0) y = a*y; b = b >> 1; if (b == 0) return y; a *= a; } }
他指出,對于所有b <15,這個操作是最優(yōu)的(算術(shù)或邏輯運算的最小數(shù)量)。對于a^b
除了廣泛的b之外的任何b ,找到計算最佳因子序列的一般問題也沒有已知的解決方案。搜索。這是一個NP難問題。所以基本上這意味著二進制分解和它一樣好。
- 3 回答
- 0 關(guān)注
- 655 瀏覽
添加回答
舉報