是否有任何函数的定义,如 sqrt()
, sin()
, cos()
, tan()
, log()
, exp()
(这些来自math.hcmath)可用吗?
我只是想知道它们是如何工作的。
这是一个有趣的问题,但阅读高效库的来源不会让你走得很远,除非你碰巧知道使用的方法。
这里有一些指针可以帮助你了解经典的方法。我的信息绝非准确。以下方法只是经典的方法,特定的实现可以使用其他方法。
sincos
函数。atan2
是通过调用 sincos
和一点逻辑。这些函数是复数运算的基础。每个实现可能都不一样,但你可以从glibc(GNU C库)的源代码中查看一个实现。
edit: Google Code Search 已经下线,所以我的旧链接无法找到。
glibc数学库的源代码在这里。
看看如何 glibc
实现了各种数学函数,充满了神奇,近似和汇编。
一定要看一看 fdlibm 源。它们很好,因为fdlibm库是自成一体的,每个函数都有详细的数学解释,而且代码非常清晰易读。
看了很多数学代码,我建议不要看glibc--代码往往相当难懂,而且很大程度上依赖于glibc的魔法。在这里,我建议大家不要看glibc--代码往往相当难懂,而且很大程度上依赖于glibc的魔法。FreeBSD中的数学库 更容易阅读,尽管有时会慢一些(但不会慢很多)。
对于复杂函数来说,主要的困难是边框情况--正确的naninf0处理对于实际函数来说已经很困难了,但对于复杂函数来说却是一场噩梦。C99标准定义了很多角案例,有些函数很容易就有10-20个角案例。你可以看一下最新的附件G C99标准文件 来了解一下。长双数也有困难,因为它的格式没有标准化--根据我的经验,你应该可以预料到长双数会有不少bug。希望即将到来的带有扩展精度的IEEE754修订版能够改善这种情况。
大多数现代硬件都包含浮点单元,可以非常有效地实现这些功能。
使用方法:根(数,根,深度)
例子:根(16,2)==sqrt(16)==4。例子:根(16,2,2) == sqrt(sqrt(16)) == 2。例子:根(64,3) == 4。
在C#中实现:
double root(double number, double root, double depth = 1f)
{
return Math.Pow(number, Math.Pow(root, -depth));
}
用途: Sqrt(Number,depth)
例子: Sqrt(16) == 4 例子: Sqrt(8,2) == sqrt(sqrt(8))
double Sqrt(double number, double depth = 1) return root(number,2,depth);
作者: Imk0tter
这些几乎都是作为系统调用来实现的。如果你想看源码,你需要访问操作系统的源码,这意味着你需要看一个开源的操作系统,比如Linux或BSD。