我一直在寻找用于计算的有效方法b(说a = 2和b = 50).为了开始,我决定看一下Math.Pow()函数的实现.但在.NET Reflector中,我发现的只有:
[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern double Pow(double x, double y);
Run Code Online (Sandbox Code Playgroud)
当我调用Math.Pow()函数时,我可以看到内部发生了什么的一些资源?
Han*_*ant 851
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()
Run Code Online (Sandbox Code Playgroud)
搜索"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));
}
Run Code Online (Sandbox Code Playgroud)
但不是真正的替代品,因为它累积了来自3个浮点运算的错误,并且没有处理Pow()所具有的怪异域问题.像0 ^ 0和-Infinity提升到任何功率.
Mic*_*zyk 108
Hans Passant的答案很棒,但我想补充一点,如果b是一个整数,那么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;
}
}
Run Code Online (Sandbox Code Playgroud)
他指出,对于所有b <15,这个操作是最优的(算术或逻辑运算的最小数量).对于a^b除了广泛的b之外的任何b ,找到计算最佳因子序列的一般问题也没有已知的解决方案.搜索.这是NP难问题.所以基本上这意味着二进制分解和它一样好.
das*_*ght 69
如果免费提供C版本的pow任何指示,它看起来不像你期望的任何东西.它不会是太大的帮助您找到.NET版本,因为你要解决(即一个与整数)的问题是大小简单的订单,可以在C#几行代码来解决与幂通过平方算法.
| 归档时间: |
|
| 查看次数: |
44993 次 |
| 最近记录: |