cos泰勒级数展开的递归算法c++

Kea*_*lls 3 c++ math recursion trigonometry

我最近写了一个计算机科学考试,他们要求我们给出 cos 泰勒级数展开式的递归定义。这是系列

cos(x) = 1 - x^2/2!+ x^4/4!+ x^6/6!...

函数签名如下所示

float cos(int n , float x)
Run Code Online (Sandbox Code Playgroud)

其中 n 表示用户想要计算的系列中的数字, x 表示 cos 函数中 x 的值

我显然没有正确回答这个问题,过去几天我一直在试图弄清楚,但我遇到了砖墙

有没有人能帮我从某个地方开始?

Cim*_*ali 5

到目前为止,所有答案每次都重新计算阶乘。我肯定不会那样做。相反,你可以写:

float cos(int n, float x)
{
    if (n > MAX)
         return 1;
    return 1 - x*x / ((2 * n - 1) * (2 * n)) * cos(n + 1, x);
}
Run Code Online (Sandbox Code Playgroud)

考虑到 cos 返回以下内容(抱歉点位置):

cos函数公式

您可以看到,对于 n>MAX、n=MAX 等情况也是如此。x 的符号交替和幂很容易看到。

最后,在 n=1 时,您会得到 0!= 1,所以调用cos(1, x)可以得到 cos 泰勒展开式的第一个 MAX 项。

通过开发(当它的项很少时更容易看到),您可以看到第一个公式等效于以下内容:

重新制定cos公式

对于 n > 0,您在 cos(n-1, x) 中除以 (2n-3)(2n-2) 前一个结果,然后乘以 x²。您可以看到,当 n=MAX+1 时,此公式为 1,n=MAX 时为 1,1-x²/((2MAX-1)2MAX)依此类推。

如果您允许自己使用辅助函数,那么您应该将上面的签名更改为float cos_helper(int n, float x, int MAX)并像这样调用它:

float cos(int n, float x) { return cos_helper(1, x, n); }


编辑:要将n评估项的度数(到目前为止的这个答案)的含义颠倒为项数(如问题中和下面),但仍然不每次都重新计算总阶乘,我建议使用两期关系。

让我们简单地定义cos(0,x) = 0cos(1,x) = 1,并尝试一般地实现 cos(n,x) 泰勒级数的 n 个第一项的总和。

然后对于每个 n > 0,我们可以从 cos(n-1,x) 写出 cos(n,x) :

cos(n,x) = cos(n-1,x) + x 2n / (2n)!

现在对于 n > 1,我们尝试使 cos(n-1,x) 的最后一项出现(因为它是我们想要添加的最接近的一项):

cos(n,x) = cos(n-1,x) + x² / ((2n-1)2n) * ( x 2n-2 / (2n-2)! )

通过将此公式与前一个公式相结合(将其调整为 n-1 而不是 n):

cos(n,x) = cos(n-1,x) + x² / ((2n-1)2n) * ( cos(n-1,x) - cos(n-2,x) )

我们现在有了 cos(n,x) 的纯粹递归定义,没有辅助函数,没有重新计算阶乘,n 是泰勒分解总和中的项数。

但是,我必须强调以下代码的性能会很差:

  • 性能明智,除非某些优化允许不重新cos(n-1,x)评估在上一步评估为cos( (n-1) - 1, x)
  • 精度明智,因为抵消效应:我们得到 x 2n-2 / (2n-2)的精度!很糟糕

现在这个免责声明已经到位,代码如下:

float cos(int n, float x)
{
    if (n < 2)
        return n;
    float c = x * x / (2 * (n - 1) * 2 * n);
    return (1-c) * cos(n-1, x) + c * cos(n-2, x);
}
Run Code Online (Sandbox Code Playgroud)