练习的目标是使用Maclaurin系列公式评估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”的结果很奇怪。为什么呢?
答案 0 :(得分:4)
这里有三个问题。
正如Mukit Chowdhury回答的那样,多头不能容纳大量的因子。但是,正如GregS评论的那样,16!应该没问题。使用长按21时,你应该会得到奇怪的结果!或更高,但您不需要更改此输入的因子函数。不过,您可能应该使用类似下面的内容:
double factorial(int n)
{
int i;
double result = 1;
for (i = 1; i <= n; i++)
result *= i;
return result;
}
在输入“12 16”上,您的代码声称正在计算16阶Maclaurin多项式,但它计算的是33阶Maclaurin多项式。 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!的项,您应该能够正确计算多项式的值。
答案 1 :(得分:3)
MacLauring的两个术语或正弦的泰勒系列之间的商是
-x*x/(2*k*(2k+1))
可以利用这一点来避免所有权力和因子及其溢出。
mxx = -x*x;
term = mxx / 6;
sum = 1+term;
k=2;
while( not good enough )
term = term*mxx/(2*k*(2*k+1));
sum = sum + term;
k = k+1;
return sum*x
答案 2 :(得分:3)
在这里我会做很多不同的事情。
我有点偏向于不得不编写数字软件,不仅能得到正确的结果而且能快速得到它们,但我在这里看到了很多浪费的计算。例如,考虑该系列的两个连续的非零项
(x ^ 13)/(13!)和 - (x ^ 15)/(15!)。如果你已经知道了它的价值
(x ^ 13)/(13!),你需要做多少计算才能获得 - (x ^ 15)/(15!)?
答案是,比计算(x ^ 13)/(13!)要少得多。
首先。如果你盲目地遵循通常的公式
对于MacLaurin系列并重新计算每个新术语的阶乘,
为了得到15!你将重复你已经做过的所有计算
为13!,然后只执行两次新的乘法。
要有效地计算这个系列而不浪费计算和没有
引入不必要的大数(以及所有可能的问题
他们可以导致,即使你使用浮点数,)
只看一个非零项之间的比例
而下一个。它易于计算,不涉及拖入
pow
函数。
一个好的算法可以让你轻松地增加术语数量,直到最后一个
term是浮点数的精度,
只要你使用合理的x输入值。
(没有必要x大于2 * pi,或者真的如此
没有任何理由将x设置为大于pi / 2,因为任何更大的正弦值
x的值可以从该范围内输入的正弦值中找到。)
答案 3 :(得分:2)
以下是我用Java编写的方法(易于转换为C ++):
package math;
/**
* Sine using Maclauren series
* @author Michael
* @link http://stackoverflow.com/questions/29445615/approximating-of-sine-and-the-remainder
* @since 4/4/2015 8:37 PM
*/
public class Sine {
private static final double TWO_PI = 2.0*Math.PI;
private static final int numPoints = 21;
private static final int numTerms = 21;
public static void main(String[] args) {
double x = -Math.PI;
double dx = 2.0*Math.PI/(numPoints-1);
for (int i = 0; i < numPoints; ++i) {
System.out.println(String.format("# terms: %d angle (radians) %10.6f sine: %15.10f", numTerms, x, sine(x, numTerms)));
x += dx;
}
}
public static double sine(double radians, int numTerms) {
double value = 0.0;
// Start by making sure the angle -pi/2 <= x <= +pi/2
double x = normalizeAngle(radians);
double term = x;
for (int n = 3; n < numTerms; n += 2) {
value += term;
term *= -x*x/n/(n-1);
}
return value;
}
public static double normalizeAngle(double radians) {
return radians - TWO_PI*Math.floor((radians+Math.PI)/TWO_PI);
}
}
这是输出:
java math.Sine
# terms: 21 angle (radians) -3.141593 sine: -0.0000000224
# terms: 21 angle (radians) -2.827433 sine: -0.3090169974
# terms: 21 angle (radians) -2.513274 sine: -0.5877852526
# terms: 21 angle (radians) -2.199115 sine: -0.8090169944
# terms: 21 angle (radians) -1.884956 sine: -0.9510565163
# terms: 21 angle (radians) -1.570796 sine: -1.0000000000
# terms: 21 angle (radians) -1.256637 sine: -0.9510565163
# terms: 21 angle (radians) -0.942478 sine: -0.8090169944
# terms: 21 angle (radians) -0.628319 sine: -0.5877852523
# terms: 21 angle (radians) -0.314159 sine: -0.3090169944
# terms: 21 angle (radians) 0.000000 sine: 0.0000000000
# terms: 21 angle (radians) 0.314159 sine: 0.3090169944
# terms: 21 angle (radians) 0.628319 sine: 0.5877852523
# terms: 21 angle (radians) 0.942478 sine: 0.8090169944
# terms: 21 angle (radians) 1.256637 sine: 0.9510565163
# terms: 21 angle (radians) 1.570796 sine: 1.0000000000
# terms: 21 angle (radians) 1.884956 sine: 0.9510565163
# terms: 21 angle (radians) 2.199115 sine: 0.8090169944
# terms: 21 angle (radians) 2.513274 sine: 0.5877852526
# terms: 21 angle (radians) 2.827433 sine: 0.3090169974
# terms: 21 angle (radians) 3.141593 sine: -0.0000000224
Process finished with exit code 0
答案 4 :(得分:0)
你的factorial()返回长,而它的返回类型是 double 。
最重要的是,长不能包含 16!。哪个加倍可以。