Math.Pow()是如何在.NET Framework中实现的?

Math.Pow()是如何在.NET Framework中实现的?

我一直在寻找用于计算的有效方法b(说a = 2b = 50)。为了开始,我决定看一下Math.Pow()函数的实现。但在.NET Reflector中,我发现的只有:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]public static extern double Pow(double x, double y);

当我调用Math.Pow()函数时,我可以看到内部发生了什么的一些资源?


慕村225694
浏览 623回答 3
3回答

猛跑小猪

MethodImplOptions.InternalCall这意味着该方法实际上是在用C ++编写的CLR中实现的。即时编译器使用内部实现的方法查询表,并直接编译对C ++函数的调用。查看代码需要CLR的源代码。您可以从SSCLI20发行版中获得。它是围绕.NET 2.0时间框架编写的,我发现了低级实现,Math.Pow()对于CLR的后续版本来说仍然很准确。查找表位于clr / src / vm / ecall.cpp中。Math.Pow()与此相关的部分如下所示: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。我会把你的代码留给你,只是看看你自己。它基本上检查了极端情况,然后调用CRT的版本pow()。唯一有趣的其他实现细节是表中的FCIntrinsic宏。这暗示了抖动可以将函数实现为内在函数。换句话说,用浮点机器代码指令替换函数调用。事实并非如此Pow(),没有FPU指令。但肯定是其他简单的操作。值得注意的是,这可以使C#中的浮点数学运算速度明显快于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提升到任何功率。

三国纷争

Hans Passant的答案很棒,但我想补充一点,如果b是一个整数,那么a^b可以通过二进制分解非常有效地计算。这是Henry Warren的Hacker's Delight的修改版本:public&nbsp;static&nbsp;int&nbsp;iexp(int&nbsp;a,&nbsp;uint&nbsp;b)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;y&nbsp;=&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;while(true)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((b&nbsp;&&nbsp;1)&nbsp;!=&nbsp;0)&nbsp;y&nbsp;=&nbsp;a*y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;=&nbsp;b&nbsp;>>&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(b&nbsp;==&nbsp;0)&nbsp;return&nbsp;y; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;*=&nbsp;a; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}他指出,对于所有b <15,这个操作是最优的(算术或逻辑运算的最小数量)。对于a^b除了广泛的b之外的任何b&nbsp;,找到计算最佳因子序列的一般问题也没有已知的解决方案。搜索。这是一个NP难问题。所以基本上这意味着二进制分解和它一样好。
打开App,查看更多内容
随时随地看视频慕课网APP