练习的目标是使用麦克劳林级数公式评估sin
。
#include <stdio.h>
#include <math.h>
double factorial(int n);
int main(void) {
double x, p, r;
int i, n;
printf("Enter a positive double number and a non - negative integer : \n");
scanf("%lf%d", &x, &n);
if (x <= 0) {
printf("Error: first argument must be a positive double.\n");
return -1;
}
if (n < 0) {
printf("Error: second argument must be a non - negative integer.\n");
return -1;
}
p = 0;
for (i = 0; i <= n; i++)
{
p += pow(-1, i) / factorial(2 * i + 1) * pow(x, 2 * i + 1);
}
r = fabs(sin(x) - p);
printf("The %d-th order Maclaurin polynomial function at x=%f is %f, with an error approximation of %f.\n", n, x, p, r);
getch();
return 0;
}
double factorial(int n)
{
int i;
long result = 1;
for (i = 1; i <= n; i++)
result *= i;
return result;
}
输入“12 16”时我得到奇怪的结果。为什么?
最佳答案
这里存在三个问题。
正如 Mukit Chowdhury 回答的那样,多头不能容纳大阶乘。不过,正如GregS所说,16!应该没有问题。当您使用 long 来保存 21 时,您应该会遇到奇怪的结果!或更大,但您无需更改此输入的阶乘函数。不过,您可能应该使用类似以下内容的内容:
double factorial(int n) { int i; double result = 1; for (i = 1; i <= n; i++) result *= i; return result; }
在输入“12 16”上,您的代码声称正在计算 16 阶麦克劳林多项式,但实际上计算的是 33 阶麦克劳林多项式。 16 阶多项式的项高达 -x^15/15! + 0x^16。解决此问题的一种方法是更正 for 循环,如下所示:
for (i = 1; i <= n; i+=2) { p += pow(-1, (i-1)/2) / factorial(i) * pow(x, i); }
因此,您的代码在阶乘方面遇到了问题,但这只是因为您正在计算额外的项。如果您计算的项最多为 -x^15/15!,您应该能够正确计算多项式的值。
- 16 阶麦克劳林多项式在 12 处的实际值为 -4306.756...这可能不是您所期望的,这可能是练习要点的一部分。为了获得准确的近似值,您应该期望最后一项很小,因此您需要 n!超过x^n。根据斯特林近似,n! ~ (n/e)^n,所以你想要 n > e*x,其中 e = 2.71828...,所以 n>=33。此时,误差为 0.005,将 n 增加 c 会使误差大小减小约 e^c 倍。
- 当您减去大量数字以产生较小的最终结果时, double 算术中应该会出现较大的错误。这在这里可能不是问题,因为最大项的量级仅为 2^14 左右。您仍然可以获得足够的精度,以至于您不会注意到通过添加更多项无法非常接近 sin(12)。
关于c++ - 正弦和余数的近似,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29445615/