我最近参加了一场计算机科学考试,其中要求我们给出cos泰勒级数展开的递归定义。该级数为
cos(x) = 1 - x^2/2! + x^4/4! + x^6/6! ...
函数签名如下:
float cos(int n , float x)
n代表用户想要计算到的数列中的数字,x代表cos函数中x的值。
显然,我没有正确回答这个问题,我已经试图解决它几天了,但是我卡在了一个难题上。
有没有人能够帮助我开始一些地方?
我最近参加了一场计算机科学考试,其中要求我们给出cos泰勒级数展开的递归定义。该级数为
cos(x) = 1 - x^2/2! + x^4/4! + x^6/6! ...
函数签名如下:
float cos(int n , float x)
n代表用户想要计算到的数列中的数字,x代表cos函数中x的值。
显然,我没有正确回答这个问题,我已经试图解决它几天了,但是我卡在了一个难题上。
有没有人能够帮助我开始一些地方?
到目前为止,所有的答案都是每次重新计算阶乘。我肯定不会这样做。相反,您可以这样写:
float cos(int n, float x)
{
if (n > MAX)
return 1;
return 1 - x*x / ((2 * n - 1) * (2 * n)) * cos(n + 1, x);
}
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)=0
和cos(1,x)=1
,并尝试一般实现cos(n,x),即泰勒级数的前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) - 1, x)
评估的cos(n-1,x)
现在这个免责声明已经就位,接下来是代码:
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);
}
double cos(double x, int n) {
static double p = 1, f = 1;
double r;
if(n == 0)
return 1;
r = cos(x, n-1);
p = (p*x)*x;
f = f*(2*n-1)*2*n;
if(n%2==0) {
return r+p/f;
} else {
return r-p/f;
}
}
2*n
以获得下一个阶乘。
让n
与我们需要的阶乘对齐使得这可以在两个操作中轻松完成:f = f * (n - 1)
然后 f = f * n
。when n = 1, we need 2!
when n = 2, we need 4!
when n = 3, we need 6!
n
加倍,然后从那里开始工作。我们可以写成:n = 2*n;
f = f*(n-1);
f = f*n;
如果我们这样做,我们需要更新我们的奇偶检查为if((n/2)%2==0)
,因为我们正在加倍n
的值。f = f*(2*n-1)*2*n;
,现在我们在检查它是偶数还是奇数时不必除以n
,因为n
没有被改变。cos(x)=1 - x^2/2! + x^4/4! - x^6/6! + x^8/8!.....
=1-x^2/2 (1 - x^2/3*4 + x^4/3*4*5*6 -x^6/3*4*5*6*7*8)
=1 - x^2/2 {1- x^2/3*4 (1- x^2/5*6 + x^4/5*6*7*8)}
=1 - x^2/2 [1- x^2/3*4 {1- x^2/5*6 ( 1- x^2/7*8)}]
double cos_series_recursion(double x, int n, double r=1){
if(n>0){
r=1-((x*x*r)/(n*(n-1)));
return cos_series_recursion(x,n-2,r);
}else return r;
}
就像求和一样,把它做了。
float cos(int n, float x)
中的参数n
是l
,现在就开始吧...
一些伪代码:
float cos(int n , float x)
{
//the sum-part
float sum = pow(-1, n) * (pow(x, 2*n))/faculty(2*n);
if(n <= /*Some predefined maximum*/)
return sum + cos(n + 1, x);
return sum;
}
if ( n >= 0 )
吗? - James Kanze#include <iostream>
using namespace std;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
float Cos(int n, float x) {
if (n == 0) return 1;
return Cos(n-1, x) + (n%2 ? -1 : 1) * pow (x, 2*n) / (fact(2*n));
}
int main()
{
cout << Cos(6, 3.14/6);
}
当你想要递归但函数参数不包含所需信息时,通常的技巧是引入一个辅助函数来进行递归。
我有印象在Lisp世界中,惯例是将这样的函数命名为something-
aux
(缩写为auxiliary),但那可能只是旧时代的一小群人。
无论如何,这里的主要问题是n
表示递归的自然结束点,即基本情况,然后您还需要一些索引来工作到n
。因此,这是辅助函数的另一个很好的参数候选项。另一个候选项源于考虑系列中的一个术语与前一个术语的关系。
x^(2*n)
和(2*n)!
。否则,你可能需要至少三个额外的变量:一个用于与n
比较的计数器,x
的幂值的运行值,以及阶乘的运行值。(我可能会为此创建一个类。) - James Kanze
1 - x^2/2! + x^4/4! - x^6/6! + ...
重写为1 - (x^2/2)(1 - (x^2/(3*4))(1 - (x^2/(5*6))(1 - ...)))
。 - lurker