sqrt()
、sin()
、cos()
、tan()
、log()
、exp()
(这些来自 math.h/cmath)可用?
我只是想知道它们是如何工作的。
最佳答案
这是一个有趣的问题,但是除非您碰巧知道使用的方法,否则阅读高效库的资源不会让您走得太远。
这里有一些提示可以帮助您理解经典方法。我的信息绝不准确。以下方法仅为经典方法,具体实现可以使用其他方法。
- 经常使用查找表
- 三角函数通常通过 CORDIC 实现算法(在 CPU 上或使用库)。请注意,通常正弦和余弦是一起计算的,我一直想知道为什么标准 C 库不提供
sincos
函数。 - 平方根使用 Newton's method通过一些巧妙的实现技巧:您可能会在网络上的某个地方找到 Quake 源代码的摘录,其中包含令人难以置信的 1/sqrt(x) 实现。
- 指数和对数使用 exp(2^n x) = exp(x)^(2^n) 和 log2(2^n x) = n + log2(x) 使参数接近于零(对于 log ) 并使用有理函数逼近(通常为 Padé approximants )。请注意,这个完全相同的技巧可以得到矩阵指数和对数。根据@Stephen Canon 的说法,现代实现倾向于泰勒展开而不是有理函数逼近,其中除法比乘法慢得多。
- 可以从这些函数中推导出其他函数。实现可能会提供专门的例程。
- pow(x, y) = exp(y * log(x)),所以当 y 为整数时,不使用 pow
- hypot(x, y) = abs(x) sqrt(1 + (y/x)^2) if x > y(hypot(y, x) 否则)以避免溢出。
atan2
是通过调用sincos
和一些逻辑来计算的。这些函数是复杂算术的构建 block 。 - 其他超越函数(gamma, erf, bessel, ...)请引用优秀书籍Numerical Recipes, 3rd edition一些想法。好老的Abramowitz & Stegun也很有用。 http://dlmf.nist.gov/ 有新版本.
- Chebyshev 近似、连分数展开(实际上与 Padé 近似相关)或幂级数节约等技术用于更复杂的函数(例如,如果您碰巧阅读了 erf、bessel 或 gamma 的源代码)。我怀疑它们在裸机简单的数学函数中有真正的用途,但谁知道呢。有关概述,请参阅数字食谱。
关于c++ - cmath 中 sqrt、sin、cos、pow 等的定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4541130/