【问题标题】:How do Trigonometric functions work? [closed]三角函数如何工作? [关闭]
【发布时间】:2008-12-05 20:49:25
【问题描述】:

因此,在高中数学中,可能还有大学,我们被教导如何使用三角函数、它们的作用以及它们解决的问题类型。但它们总是作为一个黑匣子呈现给我。如果你需要某个东西的正弦或余弦,你点击计算器上的 sin 或 cos 按钮,你就可以设置了。这很好。

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

【问题讨论】:

  • 您是否对三角函数是什么或如何实现感到困惑?
  • 我知道它们是什么。我知道他们做什么。我知道如何确定我需要哪些用于什么目的。我可以告诉你所有关于角度和距离之间的关系。我正在寻找的更像是约翰 D. 库克的回答。还有其他提到实际算法的人
  • 这是个好问题。例如,正弦、余弦和正切是超越函数,它们很难求解……另一方面,它们可以使用简单的泰勒级数展开来定义,这将为您提供任何有限准确度的正确答案必填。

标签: algorithm math trigonometry


【解决方案1】:

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

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

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

【讨论】:

  • 很好的答案——虽然 CORDIC 本身并不真正需要范围缩小(实际上它本身就是一个范围缩小算法);它适用于 -pi/2 和 +pi/2 之间的角度,因此您只需对该范围之外的角度进行 180 度矢量旋转。
  • 使用多项式近似的实现可能经常使用泰勒级数,但它们通常应该使用已通过 Remez 算法确定的系数。 lolengine.net/blog/2011/12/21/better-function-approximations
  • 请注意,CORDIC 使用的值表必须预先计算。所以,Taylor 可能仍然在“编译时”使用。
  • 似乎这个答案与这个类似问题的高评价答案相矛盾:stackoverflow.com/questions/2284860/…。这个答案说 sin() 函数主要是在硬件级别上实现的,而另一个是在 C 中实现的。
  • 当您无法访问快速硬件乘法时,CORDIC 不是更高效吗?带有 FPU 的嵌入式设备和带有 DSP 元素的 FPGA(其中有很多)可以非常有效地执行乘法运算。也许这个问题的答案自发布以来已经改变,或者我误解了权衡?
【解决方案2】:

编辑:Jack Ganssle 在他关于嵌入式系统的书中进行了不错的讨论,"The Firmware Handbook"

仅供参考:如果您有准确性和性能限制,泰勒级数应该用于逼近用于数值目的的函数。 (将它们保存在您的微积分课程中。)它们在单个点使用函数的analyticity,例如事实上,它的所有衍生物都存在于那个时候。它们不一定会在感兴趣的区间内收敛。通常他们在分配函数逼近的准确性方面做得很糟糕,以便在评估点附近“完美”;当您远离它时,错误通常会向上放大。如果你的函数有任何非连续导数(例如方波、三角波和它们的积分),泰勒级数会给你错误的答案。

当使用最大 N 次多项式在区间 x0 Chebyshev approximation;请参阅数字食谱进行很好的讨论。请注意,我链接到的 Wolfram 文章中的 Tj(x) 和 Tk(x) 使用了 cos 和反余弦,这些是多项式,实际上您使用递归公式来获得系数。再次,请参阅数字食谱。

编辑:维基百科在approximation theory 上有一篇半体面的文章。他们引用的其中一个来源(Hart,“计算机近似”)已绝版(并且使用过的副本往往很昂贵),但对此类内容进行了很多详细说明。 (Jack Ganssle 在他的时事通讯The Embedded Muse 第 39 期中提到了这一点。)

编辑 2:这是 Taylor 与 Chebyshev 的 sin(x) 的一些有形错误指标(见下文)。需要注意的一些要点:

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

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

范围 = -pi/2 到 +pi/2,5 级(3 项)

  • Taylor:最大误差约为 4.5e-3,f(x) = x-x3/6+x5/120
  • 切比雪夫:最大误差约为 7e-5,f(x) = 0.9996949x-0.1656700x3+0.0075134x5

范围 = -pi/2 到 +pi/2,7 级(4 项)

  • Taylor:最大误差约为 1.5e-4,f(x) = xx3/6+x5/120-x7>5040
  • 切比雪夫:最大误差约为 6e-7,f(x) = 0.99999660x-0.16664824x3+0.00830629x5-0.00018363x7支持>

范围 = -pi/4 到 +pi/4,3 级(2 项)

  • Taylor:最大误差约为 2.5e-3,f(x) = x-x3/6
  • 切比雪夫:最大误差约为 1.5e-4,f(x) = 0.999x-0.1603x3

范围 = -pi/4 到 +pi/4,5 级(3 项)

  • Taylor:最大误差约为 3.5e-5,f(x) = x-x3/6+x5
  • 切比雪夫:最大误差约为 6e-7,f(x) = 0.999995x-0.1666016x3+0.0081215x5

范围 = -pi/4 到 +pi/4,7 级(4 项)

  • Taylor:最大误差约为 3e-7,f(x) = xx3/6+x5/120-x7 /5040
  • 切比雪夫:最大误差约为 1.2e-9,f(x) = 0.999999986x-0.166666367x3+0.008331584x5-0.000194621x7

【讨论】:

  • 这条评论是错误的。每个近似值都有时间和地点。如果您不知道足够的分析来确定任何级数近似的收敛区域,则不应使用它。这适用于泰勒、切比雪夫、帕德等系列。泰勒级数通常足够好。
  • :shrug: 我不了解你,但我从来没有对仅在一个点附近评估一个小社区的函数感兴趣。即使是在一个区间上的快速最小二乘拟合也非常容易做到。任何使用泰勒级数的人都没有抓住重点。
  • @kquinn:Chebyshev 近似的收敛区域不是一个有用的概念,因为计算它们的区间是该过程的显式输入。
  • 支持,因为响应者知道 Hart 存在。 :smile: Hart 是这里的经典参考,即使我在 25 年前买了一本(印刷版)时很难找到。值得全力投资。尽可能减小范围,再加上适当的近似值,无论是 Pade、Chebychev,甚至是适当的 Taylor 级数,都是一个好方法。 Pade 或 Chebychev 近似值通常比泰勒级数更好。
  • ???那有什么不同?泰勒级数到 17 次以计算从 -2pi 到 +2pi 的 sin(x) 可能会被切比雪夫用 7 次或 9 次多项式击败。我不会有任何问题,“如果你在砍树时有时间限制,你不应该使用手锯。使用电锯。”也许我应该把“不应该”改成“我不推荐使用泰勒级数”。当然,在某些情况下你可以使用泰勒级数,但你的准确性和性能会出现问题。性能是指 CPU 执行时间。
【解决方案3】:

我相信它们是使用Taylor SeriesCORDIC 计算得出的。一些大量使用三角函数(游戏、图形)的应用程序在启动时会构建三角表,这样它们就可以查找值而不是一遍又一遍地重新计算它们。

【讨论】:

    【解决方案4】:

    查看the Wikipedia article 的三角函数。 Numerical Recipes 是了解如何在代码中实际实现它们的好地方。

    我不是一个数学家,但我对 sin、cos 和 tan “从何而来”的理解是,从某种意义上说,当您使用直角三角形时,可以观察到它们。如果您测量一堆不同直角三角形的边长并将点绘制在图表上,您可以从中得到 sin、cos 和 tan。正如 Harper Shelby 所指出的,这些函数被简单地定义为直角三角形的属性。

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

    【讨论】:

      【解决方案5】:

      最常用于计算机,幂级数表示用于计算正弦和余弦,这些用于其他三角函数。将这些系列扩展到大约 8 项计算所需的值以接近机器 epsilon(可以保持的最小非零浮点数)的精度。

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

      【讨论】:

        【解决方案6】:

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

        对于 tan()、sin() 和 cos() 函数,为简单起见,重叠的 0 到 2pi+pi/80 域被划分为 81 个相等的间隔,“锚点”位于 pi/80、3pi /80, ..., 161pi/80。然后评估并存储这 81 个锚点的 tan()、sin() 和 cos()。在三角恒等式的帮助下,为每个三角函数开发了一个麦克劳林级数函数。 ±无穷大之间的任何角度都可以提交给三角函数逼近函数,因为这些函数首先将输入角度转换为 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#() 表示同时计算 sin 和 cos。同样,ASINCOS#() 表示同时评估了 asin 和 acos。同时评估这两个数量几乎没有额外的开销。

        结果表明,如预期的那样,增加术语数量会略微增加执行时间。除了 tan() 近似值接近±无穷大的地方,即使是最少数量的项也能提供大约 12-14 位的准确度。人们会认为即使是 tan() 函数也会出现问题。

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

        【讨论】:

          【解决方案7】:

          如果您要求对 sin、cos 和 tan 进行更物理的解释,请考虑它们与直角三角形的关系。 cos(lambda) 的实际数值可以通过形成一个直角三角形,其中一个角为 lambda,并将与 lambda 相邻的三角形边的长度除以斜边的长度。同样,对于罪,使用对边除以斜边。对于切线,使用对边除以相邻边。记住这一点的经典记忆词是 SOHCHAHTOA(发音为 socatoa)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-11-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-31
            • 1970-01-01
            • 2010-11-29
            相关资源
            最近更新 更多