Math.Pow() 在 .NET Framework 中是如何实现的? [英] How is Math.Pow() implemented in .NET Framework?

查看:33
本文介绍了Math.Pow() 在 .NET Framework 中是如何实现的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找一种有效的方法来计算 ab(比如 a = 2b = 50).首先,我决定看看 Math.Pow() 函数的实现.但是在 .NET Reflector 中,我发现的只有这个:

I was looking for an efficient approach for calculating ab (say a = 2 and b = 50). To start things up, I decided to take a look at the implementation of Math.Pow() function. But in .NET Reflector, all I found was this:

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

当我调用 Math.Pow() 函数时,我可以在哪些资源中看到内部发生的事情?

What are some of the resources wherein I can see as what's going on inside when I call Math.Pow() function?

推荐答案

MethodImplOptions.InternalCall

这意味着该方法实际上是在 CLR 中实现的,是用 C++ 编写的.即时编译器会查阅包含内部实现方法的表格,并直接编译对 C++ 函数的调用.

That means that the method is actually implemented in the CLR, written in C++. The just-in-time compiler consults a table with internally implemented methods and compiles the call to the C++ function directly.

查看代码需要 CLR 的源代码.您可以从 SSCLI20 发行版 中获得.它是围绕 .NET 2.0 时间框架编写的,我发现诸如 Math.Pow() 之类的低级实现对于更高版本的 CLR 仍然基本准确.

Having a look at the code requires the source code for the CLR. You can get that from the SSCLI20 distribution. It was written around the .NET 2.0 time frame, I've found the low-level implementations, like Math.Pow() to be still largely accurate for later versions of the CLR.

查找表位于 clr/src/vm/ecall.cpp.与 Math.Pow() 相关的部分如下所示:

The lookup table is located in clr/src/vm/ecall.cpp. The section that's relevant to Math.Pow() looks like this:

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().

Searching for "COMDouble" takes you to clr/src/classlibnative/float/comfloat.cpp. I'll spare you the code, just have a look for yourself. It basically checks for corner cases, then calls the CRT's version of pow().

唯一有趣的其他实现细节是表中的 FCIntrinsic 宏.这暗示抖动可能会将函数实现为内在函数.换句话说,用浮点机器代码指令代替函数调用.Pow() 不是这种情况,它没有 FPU 指令.但是对于其他简单的操作肯定是有的.值得注意的是,这可以使 C# 中的浮点数学比 C++ 中的相同代码快得多,请查看 这个答案 原因.

The only other implementation detail that's interesting is the FCIntrinsic macro in the table. That's a hint that the jitter may implement the function as an intrinsic. In other words, substitute the function call with a floating point machine code instruction. Which is not the case for Pow(), there is no FPU instruction for it. But certainly for the other simple operations. Notable is that this can make floating point math in C# substantially faster than the same code in C++, check this answer for the reason why.

顺便说一下,如果您有完整版的 Visual Studio vc/crt/src 目录,也可以使用 CRT 的源代码.不过,您会在 pow() 上碰壁,微软从英特尔购买了该代码.不太可能比英特尔工程师做得更好.虽然我高中书的身份是我试的时候快了两倍:

By the way, the source code for the CRT is also available if you have the full version of Visual Studio vc/crt/src directory. You'll hit the wall on pow() though, Microsoft purchased that code from Intel. Doing a better job than the Intel engineers is unlikely. Although my high-school book's identity was twice as fast when I tried it:

public static double FasterPow(double x, double y) {
    return Math.Exp(y * Math.Log(x));
}

但不是真正的替代品,因为它累积了 3 个浮点运算的错误,并且不处理 Pow() 具有的怪异域问题.比如 0^0 和 -Infinity 的任意幂.

But not a true substitute because it accumulates error from 3 floating point operations and doesn't deal with the weirdo domain problems that Pow() has. Like 0^0 and -Infinity raised to any power.

这篇关于Math.Pow() 在 .NET Framework 中是如何实现的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆