c#Math.Sqrt实现

时间:2011-02-08 10:25:00

标签: c# .net math frameworks

我最近一直在使用System.Math,有一天我想知道微软将如何在库中实现Sqrt方法。所以我弹出了我最好的伙伴Reflector并尝试在库中反汇编方法,但它显示:

[MethodImpl(MethodImplOptions.InternalCall),ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern double Sqrt(double d);

那天有史以来第一次,我意识到我的孩子们依赖于框架,吃饭。

开玩笑,但我想知道MS会用什么样的算法来实现这个方法,换句话说,如果你没有库支持,你将如何在C#中编写自己的Math.Sqrt实现。

干杯

5 个答案:

答案 0 :(得分:17)

使用Reflector或Reference Source找到的具有MethodImplOptions.InternalCall属性的任何方法实际上都是在CLR中的C ++中实现的。您可以从SSCLI20发行版中获取这些源代码。相关文件是clr / src / vm / ecall.cpp,它包含一个带有函数指针的方法名称表,由JIT编译器用来直接将调用地址嵌入到生成的机器代码中。相关的表格部分是

FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
...

将你带到clr / src / classlibnative / float / comfloat.cpp

FCIMPL1_V(double, COMDouble::Sqrt, double d)
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    return (double) sqrt(d);
FCIMPLEND

它只是调用CRT功能。但这不是x86抖动中发生的情况,请注意表声明中的“内在”。你不会发现在SSLI20版本的抖动中,它是一个不受专利影响的简单版本。然而,运输方式确实将其变成了内在的:

        double d = 2.0;
        Console.WriteLine(Math.Sqrt(d));

转换为

00000008  fld         dword ptr ds:[0072156Ch] 
0000000e  fsqrt 
..etc

换句话说,Math.Sqrt()转换为单个浮点机器代码指令。检查this answer以获取有关如何轻松击败本机代码的详细信息。

答案 1 :(得分:4)

该函数将被翻译成汇编程序指令。例如x87的fsqrt指令。

您可以在软件中实现浮点数,但这很可能会慢很多。我认为Sqrt是迭代算法的典型实现。

答案 2 :(得分:2)

Google.com将为您提供比StackOverflow.com更多的答案

看看这个页面: http://en.wikipedia.org/wiki/Methods_of_computing_square_roots 一个算法可以在上面的维基页面的标题“二进制数字系统(基础2)”下找到。

但是,软件实现效率不高。现代CPU具有FPU中数学函数的硬件实现。您只需要调用处理器的正确指令(使用汇编语言或机器语言)

答案 3 :(得分:1)

public double Sqrt(int number)
{
    double x = number / 2;

    for (int i = 0; i < 100; i++) x = (x + number / x) / 2d;

    return x;
}

非常粗略的方法但是如果我使用更复杂的东西,例如log方法,你可以问“我怎样才能实现日志方法?”

答案 4 :(得分:0)

要重新创建 System.Math.Sqrt 函数,只需执行以下操作:

public static double Sqrt(double n) => Math.Pow(n, 1 / 2);