.NET Framework中如何实现Math.Pow()?
我一直在寻找一种计算b的有效方法(例如a = 2
和b = 50
)。首先,我决定看一下Math.Pow()
函数的实现。但是在.NET
Reflector中,我发现的只是:
[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]public static extern double Pow(double x, double y);
调用Math.Pow()
函数时,我能看到哪些内部资源?
回答:
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升到任何幂。
以上是 .NET Framework中如何实现Math.Pow()? 的全部内容, 来源链接: utcz.com/qa/409260.html