c - C 如何计算 sin() 和其他数学函数?

标签 c math trigonometry

我一直在仔细研究 .NET 反汇编和 GCC 源代码,但似乎无法在任何地方找到 sin() 和其他数学函数的实际实现...它们似乎总是引用其他东西。

谁能帮我找到他们?我觉得 C 运行的所有硬件都不太可能支持硬件中的触发函数,所以必须有一个软件算法某处,对吧?


我知道可以 计算函数的几种方法,并且已经编写了自己的例程来使用泰勒级数计算函数来获得乐趣。我很好奇真实的生产语言是如何做到这一点的,因为我的所有实现总是慢几个数量级,尽管我认为我的算法非常聪明(显然它们不是)。

最佳答案

在 GNU libm 中,sin 的实现是系统相关的。因此,您可以在 sysdeps 的相应子目录中的某处找到每个平台的实现。 .

一个目录包含由 IBM 贡献的 C 语言实现。自 2011 年 10 月以来,这是您调用 sin() 时实际运行的代码在典型的 x86-64 Linux 系统上。它显然比 fsin 快组装说明。源代码:sysdeps/ieee754/dbl-64/s_sin.c , 寻找 __sin (double x) .

这段代码非常复杂。没有一种软件算法在整个 x 值范围内尽可能快并且准确,因此库实现了几种不同的算法,它的第一项工作是查看 x 并决定使用哪种算法。

  • x 非常非常接近 0 时,sin(x) == x是正确答案。

  • 再远一点,sin(x)使用熟悉的泰勒级数。然而,这仅在 0 附近准确,所以...

  • 当角度超过 7° 时,将使用不同的算法,计算 sin(x) 和 cos(x) 的泰勒级数近似值,然后使用预先计算的表中的值来改进近似值.

  • 当 |x| > 2,以上算法都不起作用,因此代码首先计算一些接近 0 的值,该值可以提供给 sin。或 cos相反。

  • 还有另一个分支来处理 x 是 NaN 或无穷大。

此代码使用了一些我以前从未见过的数字技巧,但据我所知,它们可能在浮点专家中广为人知。有时候几行代码就需要好几段来解释。比如这两行

double t = (x * hpinv + toint);
double xn = t - toint;

(有时)用于将 x 减少到接近 0 的值,该值与 x 相差 π/2 的倍数,特别是 xn × π/2。无需划分或分支即可完成此操作的方法相当聪明。但是一点评论都没有!


旧的 32 位版本的 GCC/glibc 使用 fsin指令,这对于某些输入来说出奇地不准确。有一个 fascinating blog post illustrating this with just 2 lines of code .

fdlibm 对 sin 的实现在纯 C 中比 glibc 简单得多,并且有很好的评论。源代码:fdlibm/s_sin.cfdlibm/k_sin.c

关于c - C 如何计算 sin() 和其他数学函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12074147/

相关文章:

c - 使用 sscanf() 从一行中仅输出 2 个标记

php - 所有系统的浮点运算都一样吗?

javascript - 如何在 jQuery 中为平行四边形制作动画

java - 生成的积分偏向

c - 用 C 获得整数中最正确数字的最佳方法是什么?

c++ - 虚拟内存或物理内存

c - 将值设置为用户定义大小的二维数组的元素

algorithm - N个圆的共同重叠

c - 可变时间步长和加速度

matlab - 在Matlab上绘制正弦波的问题