是否有如sqrt()
, sin()
, cos()
, tan()
, log()
和exp()
(这些函数从math.h/cmath库中获取)的函数定义?
我只是想知道它们是如何工作的。
是否有如sqrt()
, sin()
, cos()
, tan()
, log()
和exp()
(这些函数从math.h/cmath库中获取)的函数定义?
我只是想知道它们是如何工作的。
这是一个有趣的问题,但是阅读高效库的源代码并不足以让你了解使用的方法。
以下是一些提示,帮助你理解经典方法。我的信息并不十分准确。以下方法仅为经典方法,具体实现可能使用其他方法。
sincos
函数。atan2
通过调用sincos
和一些小的逻辑计算。这些函数是复杂算术的构建块。exp
和log
,有理逼近法大多已经过时了,因为在现代硬件上,乘法和加法比除法快得多。然而,它仍然用于更严格的函数。 - Stephen Canon每个实现都可能是不同的,但你可以查看GNU C库(glibc)源代码中的一个实现。
编辑:Google Code Search已经下线,所以我之前的链接已经失效。
glibc的数学库源代码位于此处:
看看glibc
如何实现各种数学函数,充满了神奇、近似和汇编。
经过对数学代码的大量研究,我建议不要去看glibc的代码,因为这些代码通常很难跟踪,并且在很大程度上依赖于glibc的魔法。如果有需要,可以查看FreeBSD中的数学库,它更容易阅读,但速度可能会稍慢(但不会慢太多)。
对于复杂函数,主要困难在于边界情况——正确处理nan/inf/0对实函数已经很困难了,但对于复杂函数来说就更加困难了。C99标准定义了许多边角情况,有些函数甚至有10-20个边角情况。您可以查看最新的C99标准文档的附录G以获取一个概念。此外,还有一个问题是长双精度浮点数的格式未经标准化——根据我的经验,您应该预计会出现相当多的长双精度浮点数错误。希望即将推出的IEEE754修订版扩展精度会改善情况。
ldexp
函数使该函数几乎无用)。 - Alexandre C.现代大多数硬件都包括浮点单元,可以非常高效地实现这些函数。
用法: root(number,root,depth)
示例: root(16,2) == sqrt(16) == 4
示例: root(16,2,2) == sqrt(sqrt(16)) == 2
示例: root(64,3) == 4
C#实现:
double root(double number, double root, double depth = 1f)
{
return Math.Pow(number, Math.Pow(root, -depth));
}
用法: Sqrt(数字,深度)
示例: Sqrt(16) == 4
示例: Sqrt(8,2) == sqrt(sqrt(8))
double Sqrt(double number, double depth = 1) return root(number,2,depth);
作者:Imk0tter