三角函数如何工作?


102

因此,在中学数学乃至大学中,我们都学会了如何使用三角函数,它们的作用以及所解决的问题类型。但是它们始终以黑匣子的形式呈现给我。如果您需要某些东西的正弦或余弦,请按一下计算器上的sin或cos按钮,然后进行设置。没关系

我想知道的是通常如何实现三角函数。


您对触发功能是什么或如何实现感到困惑?
凯尔·克罗宁

15
我知道他们是什么。我知道他们在做什么。我知道如何确定我需要什么以达到什么目的。我可以告诉大家所有角度和距离之间的关系。我一直在寻找John D. Cook的答案。其他提到实际算法的人
Jurassic_C

这是一个很好的问题。例如,正弦,余弦和切线是先验函数,很难解决...另一方面,可以使用简单的泰勒级数展开来定义它们,它将在任何有限的精度范围内为您提供正确的答案需要。
亚历克斯

Answers:


144

首先,您必须进行某种范围的缩小。触发函数是周期性的,因此您需要将参数减少到标准间隔。对于初学者,您可以将角度减小到0到360度之间。但是,通过使用一些身份,您意识到可以少花钱。如果您为0到45度之间的角度计算正弦和余弦,则可以引导您的方法来计算所有角度的所有触发函数。

减少论点后,大多数芯片都会使用CORDIC算法来计算正弦和余弦。您可能会听到人们说计算机使用泰勒级数。这听起来很合理,但事实并非如此。CORDIC算法更适合高效的硬件实现。(软件库可能在不支持触发功能的硬件上使用泰勒级数。)可能会有一些额外的处理,使用CORDIC算法可获得相当好的答案,但随后可以做一些其他事情以提高准确性。

上面有一些改进。例如,对于很小的角度theta(以弧度为单位),sin(theta)= theta等于您拥有的所有精度,因此,简单地返回theta比使用其他算法更有效。因此,在实践中有很多特殊情况的逻辑可以挤出所有可能的性能和准确性。市场较小的芯片可能不会花太多精力进行优化。


4
很好的答案-尽管CORDIC本身实际上并不需要缩小范围(实际上,它本身就是缩小范围算法);它对于-pi / 2和+ pi / 2之间的角度效果很好,因此对于该范围之外的角度,您只需进行180度矢量旋转。
杰森S

3
使用多项式逼近的实现可能经常使用泰勒级数,但通常使用通过Remez算法确定的系数。lolengine.net/blog/2011/12/21/better-function-approximations
Pascal Cuoq

1
请注意,CORDIC使用的值表必须预先计算。因此,Taylor可能仍在“编译时”使用。
大黄

2
似乎该答案与对此类似问题的高评价答案相矛盾:stackoverflow.com/questions/2284860/…。这个回答说,罪()函数主要在硬件级别上实现,而另一说,在C.
佩里

48

编辑:杰克·甘斯勒(Jack Ganssle)在其有关嵌入式系统的书“固件手册”中进行了不错的讨论。

仅供参考:如果您有准确性和性能方面的限制,则不应将泰勒级数用于近似数值目的的函数。(将它们保存在您的微积分课程中。)它们在单个点上利用函数的解析性,例如,所有函数的派生都存在于该点。他们不一定会在兴趣区间内收敛。他们常常为了分配函数近似值的准确性而做得很差劲,以便在评估点附近“完美”。当您远离错误时,错误通常会向上放大。而且,如果您具有任何不连续导数的函数(例如方波,三角波及其积分),泰勒级数将给您错误的答案。

当使用最大次数N的多项式在区间x0 <x <x1上近似给定函数f(x)时,最好的“简单”解法来自Chebyshev近似;请参阅数字食谱,以获取很好的讨论。请注意,我链接到的Wolfram文章中的Tj(x)和Tk(x)使用了余弦和反余弦,它们是多项式,实际上,您可以使用递归公式来获取系数。同样,请参见数字食谱。

编辑:维基百科上有一篇关于近似理论的半体面文章。他们引用的来源之一(Hart,“计算机近似值”)已经绝版了(使用过的副本往往很昂贵),但是却涉及到很多类似的细节。(Jack Ganssle在他的时事通讯The Embedded Muse的第39期中提到了这一点。)

编辑2:这是针对sin(x)的Taylor vs. Chebyshev的一些明显的误差指标(见下文)。需要注意的重要事项:

  1. 泰勒级数逼近在给定范围内的最大误差远大于相同度数的切比雪夫逼近的最大误差。(对于大约相同的错误,使用Chebyshev可以减少一个任期,这意味着更快的性能)
  2. 缩小范围是一个巨大的胜利。这是因为,当近似间隔较小时,高阶多项式的贡献减小。
  3. 如果无法避免缩小范围,则需要更精确地存储系数。

别误会:泰勒级数将在正弦/余弦中正常工作(在-pi / 2到+ pi / 2的范围内具有合理的精度;从技术上讲,有了足够的术语,您可以为所有实际输入达到所需的精度,但请尝试使用泰勒级数计算cos(100),除非使用任意精度算术,否则您将无法做到这一点。如果使用非科学计算器将我困在荒岛上,并且需要计算正弦和余弦,由于系数容易记住,因此我可能会使用泰勒级数。但是,现实世界中必须编写自己的sin()或cos()函数的应用程序非常罕见,以至于最好使用有效的实现来达到所需的精度,而泰勒级数则并非如此

范围= -pi / 2至+ pi / 2,度5(3个条件)

  • 泰勒:约4.5E-3,F(X)= XX最大误差3 /6 + X 5 /120
  • Chebyshev:最大误差在7e-5附近,f(x)= 0.9996949x-0.1656700x 3 + 0.0075134x 5

范围= -pi / 2至+ pi / 2,度7(4个术语)

  • 泰勒:约1.5E-4,F(X)= XX最大误差3 /6 + X 5 /120-X 7 /5040
  • Chebyshev:最大误差在6e-7附近,f(x)= 0.99999660x-0.16664824x 3 + 0.00830629x 5 -0.00018363x 7

范围= -pi / 4至+ pi / 4,度3(2个术语)

  • 泰勒:约2.5E-3,F(X)最大误差= XX 3 /6
  • 切比雪夫:最大误差在1.5e-4左右,f(x)= 0.999x-0.1603x 3

范围= -pi / 4至+ pi / 4,5级(3个术语)

  • 泰勒:约3.5E-5,F(X)= XX最大误差3 /6 + X 5
  • Chebyshev:最大误差在6e-7左右,f(x)= 0.999995x-0.1666016x 3 + 0.0081215x 5

范围= -pi / 4至+ pi / 4,等级7(4个术语)

  • 泰勒:围绕3E-7,F(X)= XX最大误差3 /6 + X 5 /120-X 7 /5040
  • Chebyshev:最大误差在1.2e-9附近,f(x)= 0.999999986x-0.166666367x 3 + 0.008331584x 5 -0.000194621x 7

2
这个评论是错误的。每个近似值都有一个时间和地点。如果您不了解足够的分析方法来确定ANY系列逼近的收敛范围,则不应使用它。这适用于泰勒(Taylor),切比雪夫(Chebyshev),帕德(Padé)等系列。泰勒级数通常足够好。
kquinn

4
:shrug:我不了解您,但是我从来没有兴趣评估仅在一个点附近的小社区中的功能。即使在一个间隔内快速拟合最小二乘法也非常容易做到。任何使用泰勒级数的人都没有抓住重点。
詹森·S,2009年

1
@kquinn:Chebyshev逼近的收敛区域不是一个有用的概念,因为计算它们的间隔是该过程的显式输入。
詹森·S,2009年

2
投票是因为响应者知道Hart存在。:smile:即使我在25年前购买(印刷)副本时很难找到,Hart还是这里的经典参考书。值得全力投资。尽可能减小范围,并加上适当的近似值,例如Pade,Chebychev,甚至适当的Taylor级数,都是一个很好的方法。但是,与泰勒级数相比,Pade或Chebychev近似值通常是更好的选择。

3
??? 有什么不同吗?泰勒级数达到17度以计算-2pi至+ 2pi的sin(x)可能会被具有7或9级多项式的切比雪夫击败。我的陈述不会有任何问题,“如果砍伐树木时有时间限制,则不应使用手锯。请使用电锯。” 也许我应该将“不应该”改写为“我不建议使用泰勒级数”。当然,在某些情况下您可以使用泰勒级数,但是您的准确性和性能会出现问题。性能是指CPU执行时间。
杰森S

14

我相信它们是使用泰勒级数CORDIC计算的。一些大量使用触发功能(游戏,图形)的应用程序在启动时会构造触发表,这样它们就可以查找值,而不必一遍又一遍地重新计算它们。


6

查看有关触发功能的Wikipedia文章。学习如何在代码中实际实现它们的一个好地方是数值食谱

我不是数学家,但是我对sin,cos和tan从何而来的理解是,从某种意义上讲,当您处理直角三角形时,它们是观察到的。如果对一堆不同的直角三角形的边长进行测量,然后在图中绘制点,则可以得出正弦,余弦和正切。正如哈珀·谢尔比(Harper Shelby)所指出的那样,这些函数被简单地定义为直角三角形的属性。

通过了解这些比率与圆的几何形状之间的关系,可以获得更复杂的理解,从而得出弧度和所有优点。维基百科条目中全都有。


1

对于计算机,最常见的是幂级数表示法用于计算正弦和余弦,而这些正弦和余弦用于其他触发函数。将这些系列扩展到大约8个项,可以计算出所需的值,使其精度接近机器的epsilon(可以保留的最小非零浮点数)。

因为CORDIC方法是在硬件上实现的,所以它的速度更快,但是它主要用于嵌入式系统而不是标准计算机。


0

我想扩展@Jason S提供的答案。使用类似于@Jason S描述的域细分方法,并使用Maclaurin级数逼近,tan(),sin()的平均(2-3)X加速,通过-O3优化内置到gcc编译器中的,cos(),atan(),asin()和acos()函数得以实现。下文所述的最佳Maclaurin系列逼近函数实现了双精度精度。

对于tan(),sin()和cos()函数,为简单起见,将0到2pi + pi / 80的重叠域划分为81个等间隔,其“锚点”位于pi / 80、3pi / 80, ...,161pi / 80。然后评估和存储这81个锚点的tan(),sin()和cos()。借助触发身份,为每个触发功能开发了一个Maclaurin系列功能。±无限大之间的任何角度都可以提交给trig逼近函数,因为函数首先将输入角度转换为0到2pi域。该转换开销包括在近似开销中。

针对atan(),asin()和acos()函数开发了类似的方法,其中将-1.0到1.1的重叠域划分为21个等间隔,锚点位于-19 / 20,-17 / 20等。 。,19/20,21/20。然后,仅存储这21个锚点中的atan()。同样,借助逆触发身份,为atan()函数开发了一个Maclaurin系列函数。然后使用atan()函数的结果来近似asin()和acos()。

由于所有逆三角函数逼近函数均基于atan()逼近函数,因此允许使用任何双精度参数输入值。但是,输入到asin()和acos()逼近函数的参数将被截断为±1域,因为它以外的任何值都是没有意义的。

为了测试近似函数,必须对十亿个随机函数求值进行求值(也就是说,-O3优化编译器由于无法使用某些计算结果而不能绕过某项求值。)要消除对十亿个求值的偏见随机数并处理结果,则首先执行不评估任何三角函数或反三角函数的运行成本。然后从每个测试中减去此偏差以获得实际功能评估时间的更具代表性的近似值。

表2.执行指示的功能或执行十亿次的时间(以秒为单位)。通过从表1的其余行中减去评估表1的第一行中所示的十亿个随机数的时间成本来获得估计值。

在tan()中花费的时间:18.0515 18.2545

在TAN3()中花费的时间:5.93853 6.02349

在TAN4()中花费的时间:6.72216 6.99134

在sin()和cos()中花费的时间:19.4052 19.4311

在SINCOS3()中花费的时间:7.85564 7.92844

在SINCOS4()中花费的时间:9.36672 9.57946

在atan()中花费的时间:15.7160 15.6599

在ATAN1()中花费的时间:6.47800 6.55230

在ATAN2()中花费的时间:7.26730 7.24885

在ATAN3()中花费的时间:8.15299 8.21284

在asin()和acos()中花费的时间:36.8833 36.9496

在ASINCOS1()中花费的时间:10.1655 9.78479

在ASINCOS2()中花费的时间:10.6236 10.6000

在ASINCOS3()中花费的时间:12.8430 12.0707

(为了节省空间,未显示表1。)表2显示了每个近似函数的十亿次评估的两次单独运行的结果。第一列是第一轮,第二列是第二轮。函数名称中的数字“ 1”,“ 2”,“ 3”或“ 4”表示Maclaurin系列函数中用于评估特定三角函数或逆三角函数逼近的项数。SINCOS#()表示同时评估了正弦和余弦。同样,ASINCOS#()表示同时评估了asin和acos。同时评估两个数量几乎没有额外的开销。

结果表明,增加术语数量会稍微增加执行时间,这是可以预期的。除了tan()近似值接近±无穷大附近的位置以外,即使是最少数量的项也可以在任何地方提供约12-14位的精度。人们甚至会期望tan()函数在那里出现问题。

在Unix高端MacBook Pro笔记本电脑和Linux高端台式机上也获得了类似的结果。


-5

如果您要对罪,余弦和棕褐色作更实际的解释,请考虑它们与直角三角形的关系。cos(λ)的实际数值可以通过以下方式求出:形成一个直角三角形,其中一个角度为lambda,然后将与lambda相邻的三角形边的长度除以斜边的长度。同样地,对于罪恶,请使用斜边除以反面。对于切线,请使用相对侧除以相邻侧。要记住的经典备忘录是SOHCAHTOA(发音为socatoa)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.