2011-02-08 83 views
10

最近我一直在使用System.Math,并且有一天我想知道Microsoft如何在库中实现Sqrt方法。所以我拧开我的最佳搭档反射器,并试图拆卸库的方法,但它表明:c#Math.Sqrt实现

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

当天的第一次,我意识到我的孩子怎么养都是在框架上,吃。

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

干杯

+6

出于兴趣,我们最好的伴侣将在3月份时花费35美元...... – StuartLC 2011-02-08 10:30:29

回答

17

您使用Reflector或具有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 /漂浮/ 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了解如何轻松击败本机代码。

4

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

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

2

Google.com会给你比StackOverflow.com

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

但是,软件实现将不会有效。现代CPU具有用于FPU数学函数的硬件实现。你只需要调用(汇编或机器语言)

+0

即使存储在硬件中并称为微型程序,它仍然是软件。 – 2011-02-08 10:39:30

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

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

    return x; 
} 

非常粗略的方法处理器的正确说明,但如果我用的更精致,如日志的方法,你可以问:“我怎么能实现日志方法?“

+0

我不确定是否会得到最低有效位(s)正确。 – CodesInChaos 2011-02-08 10:38:25

+0

嗯,当然。这就是为什么我说这是非常“粗糙”的,当然,你可以迭代更多的次数来达到足够的误差,但是这会使算法变得不可读。 `2d`为`2`为`double`。 – 2011-02-08 10:41:29