C程序 – 泰勒series_long公式

这个公式来自我的一个朋友—我为他修好了。 但我似乎无法弄清楚如何在每个角度进行正确的正弦计算。 有人可以帮助我在罪恶部分得到正确的命令吗?

码:

#include #define PI 3.141592653589 #define NUMBER_OF_TERMS 10 double factorial(double x) { double counter, total; counter=x; total=x; while(counter>1) { counter--; total = total * counter; } return total; } double power(double x, double y) { double counter, j; counter=0; j = x; while (counter<(y-1)) { counter++; x = x * j; } return x; } double cosine_func(double radians) { int counter, x; double cosine; x=0; counter=0; cosine = 0; while(counter<NUMBER_OF_TERMS-1) { counter++; x=x+2; if(counter%2 == 0) { cosine = cosine - (power(radians, x)/factorial(x)); } else if(counter%2 != 0) { cosine = cosine + (power(radians, x)/factorial(x)); } } return cosine; } double sine_func(double radians) { int counter, x; double sin; x=0; counter=0; sin = 0; while(counter<NUMBER_OF_TERMS-2) { counter++; x=x+3; if(counter%2 != 0) { sin= sin -(power(radians, x)/factorial(x)); } else if(counter%2 != 0) { sin= sin + (power(radians, x)/factorial(x)); } } return sin; } main() { double counter; double x_angles; double x_radians; double cosine; double sin; printf("11526769\n\n"); printf("x(degrees)\tx(radians)\t\t cos x\t\t sin x\t\t"); counter = 0; x_angles = -185; while (x_angles<180) { counter++; x_angles+=5; x_radians=x_angles*PI/180.0; cosine=1-cosine_func(x_radians); sin=x_radians-sine_func(x_radians); printf("%.2lf\t\t%.12lf\t\t%.12lf\t\t%.12lf\n", x_angles, x_radians, cosine, sin); } return 0; } 

 for(f2=3;f2==1;f2--){ fac2*=f2; } 

f2用3初始化,然后在条件部分检查f2是否等于1 ,返回false。

此循环甚至不会运行一次。 条件第一次是假的。 所以

 fac2*=f2; 

从未被执行过。

你为每个下一个循环做了同样的错误。

你的大多数for循环都不会运行。 检查它们的正确语法。 例:

 for(f2=3;f2==1;f2--) 

永远不会执行,因为f2 = 3和3!= 1

 #include #define PI 3.141592653589 #define NUMBER_OF_TERMS 10 int main() { double angle_degrees, angle_radians; double sin, i, i2, i3, i4 , i5, i6, i7, i8, i9, i10; double fac1, fac2, fac3, fac4, fac5, fac6=1, fac7, fac8, fac9, fac10; double f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; double p1, p2, p3, p4, p5, p6, p7, p8, p9, p10; for(angle_degrees = -180; angle_degrees <= 180; angle_degrees += 5){ p1 = angle_radians; p2 = angle_radians; p3 = angle_radians; p4 = angle_radians; p5 = angle_radians; p6 = angle_radians; p7 = angle_radians; p8 = angle_radians; p9 = angle_radians; p10 = angle_radians; angle_radians = angle_degrees*PI/180; for(f1=3;f1>=1;f1--){ fac1*=f1; } for(f2=5;f2>=1;f2--){ fac1*=f2; } for(f3=7;f3>=1;f3--){ fac1*=f3; } for(f4=9;f4>=1;f4--){ fac1*=f4; } for(f5=11;f5>=1;f5--){ fac1*=f5; } for(f6=13;f6>=1;f6--){ fac1*=f6; } for(f7=15;f7>=1;f7--){ fac1*=f7; } for(f8=17;f8>=1;f8--){ fac1*=f8; } for(f9=19;f9>=1;f9--){ fac1*=f9; } for(f10=21;f10>=1;f10--){ fac1*=f10; } sin = angle_radians - (pow(p1, 3)/fac1) + (pow(p2, 5)/fac2) - (pow(p3, 7)/fac3) + (pow(p4, 9)/fac4) - (pow(p5, 11)/fac5) + (pow(p6, 13)/fac6) - (pow(p7, 15)/fac7) + (pow(p8, 17)/fac8) -(pow(p9, 19)/fac9) - (pow(p10, 21)/fac10); printf ("%.2lf\t\t%.12lf\t\t%.12lf\n", angle_degrees, angle_radians, sin); } } 

这是一个全新的 – 我也忘记了它涉及的这些限制:1)除了main()之外没有其他function。 2)涉及无输入。 3)角度=双倍数据。 4)输出=角度(度和弧度),余弦(一旦完成求解正弦就会起作用)和正弦。

sin(x)的泰勒级数是xx ^ 3/3!+ x ^ 5/5!-… 在你的代码中,我假设p1应该表示x ^ 1 = x,p2 = x ^ 3,..和f1 = 1! f2 = 3!,.. 现在在你写的结果行中

  sin = angle_radians - (p1/fac1) + (p2/fac2) + //... 

其中系列错误符号+第一个词。

  sin = (p1/fac1) - (p2/fac2) + //... 

代码也过于复杂。 您可以在一个循环中收集结果:

 double p=x; double f=1; double res=0; int k=1; for (int i=0;i 

这里x是以弧度表示的角度,p是具有右符号的当前功率,f是该术语的阶乘。

正如LutzL所评论的那样,由于阶乘而在某种程度上会溢出。 此版本对溢出更安全

 double res=0; double term=x; int k=1; for (int i=0;i 

代码可以比sin(D2R(angle_degrees))做得更好sin(D2R(angle_degrees))

步骤1:在转换为弧度之前将角度减小到0到90度的范围。 利用通常的触发身份。 然后我们得到90 * n度的确切答案。

步骤2:计算从上一个项到第一个项的幂级数,因为求和小项首先更准确。

 #include #define PI 3.1415926535897932384626433832795 #define D2R(a) ((a)*PI/180) #define NUMBER_OF_TERMS 10 int main(void) { double angle_degrees; for (angle_degrees = -360; angle_degrees <= 360; angle_degrees += 30) { double angle_radians = D2R(angle_degrees); int sign = 1; double angle_reduced_degrees = fmod(angle_degrees, 360.0); if (angle_reduced_degrees < 0) { angle_reduced_degrees = -angle_reduced_degrees; sign = -1; } int quadrant = (int) (angle_reduced_degrees / 90.0); angle_reduced_degrees -= quadrant * 90; switch (quadrant) { case 0: break; case 1: angle_reduced_degrees = 90 - angle_reduced_degrees; break; case 2: angle_reduced_degrees = -angle_reduced_degrees; sign = -sign; break; case 3: angle_reduced_degrees = 90 - angle_reduced_degrees; sign = -sign; break; } double angle_reduced_radians = D2R(angle_reduced_degrees); long long denom = 1; for (int i = 1; i < NUMBER_OF_TERMS; i++) { denom *= -(2 * i + 0) * (2 * i + 1); } double aa = angle_reduced_radians * angle_reduced_radians; double sum = 0; for (int i = NUMBER_OF_TERMS; --i >= 0;) { double term = 1.0 / (double) denom; sum = term + sum * aa; if (i) denom /= (-(2 * i) * (2 * i + 1)); } sum *= angle_reduced_radians * sign; sum *= 1.0; // to get rid of -0.0 printf("sine(%+7.2f degrees %+9f radians) = %+20.17f sin()=%+20.17f\n", angle_degrees, angle_radians, sum, sin(angle_radians)); } return 0; } 

产量

 sine(-360.00 degrees -6.283185 radians) = -0.00000000000000000 sin()=+0.00000000000000024 sine(-330.00 degrees -5.759587 radians) = +0.50000000000000000 sin()=+0.49999999999999967 sine(-300.00 degrees -5.235988 radians) = +0.86602540378443871 sin()=+0.86602540378443860 sine(-270.00 degrees -4.712389 radians) = +0.99999999999999989 sin()=+1.00000000000000000 sine(-240.00 degrees -4.188790 radians) = -0.86602540378443871 sin()=+0.86602540378443882 sine(-210.00 degrees -3.665191 radians) = -0.50000000000000000 sin()=+0.50000000000000011 sine(-180.00 degrees -3.141593 radians) = -0.00000000000000000 sin()=-0.00000000000000012 sine(-150.00 degrees -2.617994 radians) = -0.50000000000000000 sin()=-0.49999999999999994 sine(-120.00 degrees -2.094395 radians) = -0.86602540378443871 sin()=-0.86602540378443860 sine( -90.00 degrees -1.570796 radians) = -0.99999999999999989 sin()=-1.00000000000000000 sine( -60.00 degrees -1.047198 radians) = -0.86602540378443871 sin()=-0.86602540378443871 sine( -30.00 degrees -0.523599 radians) = -0.50000000000000000 sin()=-0.50000000000000000 sine( +0.00 degrees +0.000000 radians) = +0.00000000000000000 sin()=+0.00000000000000000 sine( +30.00 degrees +0.523599 radians) = +0.50000000000000000 sin()=+0.50000000000000000 sine( +60.00 degrees +1.047198 radians) = +0.86602540378443871 sin()=+0.86602540378443871 sine( +90.00 degrees +1.570796 radians) = +0.99999999999999989 sin()=+1.00000000000000000 sine(+120.00 degrees +2.094395 radians) = +0.86602540378443871 sin()=+0.86602540378443860 sine(+150.00 degrees +2.617994 radians) = +0.50000000000000000 sin()=+0.49999999999999994 sine(+180.00 degrees +3.141593 radians) = +0.00000000000000000 sin()=+0.00000000000000012 sine(+210.00 degrees +3.665191 radians) = +0.50000000000000000 sin()=-0.50000000000000011 sine(+240.00 degrees +4.188790 radians) = +0.86602540378443871 sin()=-0.86602540378443882 sine(+270.00 degrees +4.712389 radians) = -0.99999999999999989 sin()=-1.00000000000000000 sine(+300.00 degrees +5.235988 radians) = -0.86602540378443871 sin()=-0.86602540378443860 sine(+330.00 degrees +5.759587 radians) = -0.50000000000000000 sin()=-0.49999999999999967 sine(+360.00 degrees +6.283185 radians) = +0.00000000000000000 sin()=-0.00000000000000024 

可以进行一些小的改进。

代码允许任意数量的术语

从https://stackoverflow.com/a/28227419/3088138复制自己


避免重新计算递归函数,如相同参数和阶乘的幂,总是一个好主意。 因此,减少到(最小量)基本算术运算如下所示:

 public static double sine(int terms, double x) { double result = 1; double mxx = -x*x; double addens = 1; double temp = 2; for(int n = 2; n <= terms; n++) { addens *= mxx/temp++/temp++; result += addens; } return x*result; } 

要学习生产质量实现,你可以访问基本计算器bc的数学库libmath,可以在http://code.metager.de/source/xref/gnu/bc/1.06/bc/libmath上阅读gnu版本。 .B

它使参数wrt正常化。 pi然后使用泰勒系列的罪。


固定数量术语的类似Horner的模式

如果您在电源系列中受限于固定数量的术语,则可以使用类似Horner的代码进行评估。 例如,接下来是4个术语

 xx^3/3!+x^5/5!-x^7/7! = x*(1-x²/6*(1-x²/20*(1-x²/42))) 

这可以放入循环中

 res = 1 for( k=num_terms; k-->1;) { res = 1-x*x*res/(2*k*(2*k+1)) } res = res*x; 

或者你可以展开循环

 res = 1-x*x/42; res = 1-x*x/20*res; res = 1-x*x/6*res; res = x*res; 

您可以自由组合x2=x*x或重命名x=angle_radians