c#Math.Sqrt实现
我最近一直在使用System.Math,有一天我想知道微软将如何在库中实现Sqrt方法。 所以我弹出了我最好的伙伴Reflector并尝试反汇编库中的方法,但它显示:
[MethodImpl(MethodImplOptions.InternalCall),ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern double Sqrt(double d);
那天有史以来第一次,我意识到我的孩子依赖于框架,吃饭。
开玩笑,但我想知道MS将用什么样的算法来实现这个方法,换句话说,如果你没有库支持,你将如何在C#中编写自己的Math.Sqrt实现。
干杯
使用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
它只是调用CRTfunction。 但这不是x86抖动中发生的情况,请注意表声明中的“内在”。 你不会发现在SSLI20版本的抖动中,它是一个不受专利影响的简单版本。 但运输方式确实将其变成了内在的:
double d = 2.0; Console.WriteLine(Math.Sqrt(d));
翻译成
00000008 fld dword ptr ds:[0072156Ch] 0000000e fsqrt ..etc
换句话说,Math.Sqrt()转换为单个浮点机器代码指令。 请查看此答案 ,详细了解如何轻松地击败本机代码。
该函数将被转换为汇编程序指令。 比如x87的fsqrt
指令。
您可以在软件中实现浮点数,但这很可能会慢很多。 我认为对于Sqrt来说,迭代算法是典型的实现方式。
Google.com将为您提供比StackOverflow.com更多的答案
看看这个页面: http : //en.wikipedia.org/wiki/Methods_of_computing_square_roots在上面的维基页面的标题“二进制数字系统(基础2)”下可以找到一种算法。
但是,软件实现效率不高。 现代CPU具有FPU中数学函数的硬件实现。 您只需要调用处理器的正确指令(使用汇编语言或机器语言)
public double Sqrt(int number) { double x = number / 2; for (int i = 0; i < 100; i++) x = (x + number / x) / 2d; return x; }
非常粗糙的方法,但如果我使用更精细的东西,如日志方法,你可以问“我怎么能实现日志方法?”