这是我为学校作业用 Tayilo 的序列计算正弦的一个小程序 我有。有人有更好的主意吗?我的意思是它有效,但还可以更好
#include <stdio.h>
#include <math.h>
int main(int argc, int **argv){
system ("chcp 1253");
int deg, i, a=(-1), flag=0;
double pi=3.14159265359, x, sinx, o1, o2; //pi is rounded up to the last digit
printf("Δώσε γωνία σε μοίρες από 0-2π (0-360):"); //translate: give angle in degrees
scanf("%d",°);
x=(pi/180)*deg; //apo moires se rad (metavlith x)
o2=((x*x*x)/6)*a;
sinx=x+o2;
for(i=4; flag!=1; i+=2){
o1=a*o2*((x*x)/(i*(i+1)));
if (fabs(o2-o1)<=0.000001){
flag=1;
};
sinx=sinx+o1;
o2=o1;
};
printf("\nΤο ημίτονο του %d είναι: %f", deg, sinx); //the sine of %d is ...
return 0;
};
在我的菜鸟眼中,代码没有任何问题,但我确信它可以改进。
有人有更好的主意吗?我的意思是它有效,但还可以更好
近似圆周率
“pi 向上舍入到最后一位数字”错误地表述了 最后一位数字。使用这样的舍入值没有任何优势。
double
通常具有 53 位精度。 pi 至少使用 17 位有效小数位。您的系统将尽其所能。
// double pi=3.14159265359
double pi=3.1415926535897932384626433832795
它的浮动点
double
被编码为 floating 点,而不是 fixed 点。 fabs(o2-o1)<=0.000001
是对 fixed 点算法的有用比较。相反,终止条件应该接近从“浮动”角度结束的系列。
// fabs(o2-o1)<=0.000001
#define MY_EPSILON 0.000001
fabs(o2-o1)<= fabs(o1)*MY_EPSILON
我会使用更精细的epsilon
,也许是 1.0e-15,并避免使用赤裸裸的幻数。 同样,
"%f"
报告小数点后有固定位数。当正弦算法对于小角度非常有效时,此报告针对所有小角度为 0.000000。使用
"%g"
或 "%.15g"
了解更多详细信息。这里使用的 printf()
precision与上面使用的 epsilon 有关。 代码是从小项到大项计算
这比另一个方向稍好一些,但更难确定何时停止。
大值当范围远离[-90...+90]度时,泰勒级数收敛缓慢。使用三角函数将角度调整为 [0...+/-45] 度。然后还编写一个
cosine()
例程。
将范围缩小为弧度是很棘手的,因为 pi 是一个无理数。因此,先减小角度,以度为单位。对于 fmod()
,这通常是
精确。
deg = fmod(deg, 360.0);
示例替代方案(未经测试,并且仍然缺乏除 [-360...+360] 之外的范围缩小 - 尚未完成的事情):#include <math.h>
double sine(double x_degrees) {
static const double d2r = 3.1415926535897932384626433832795 / 180.0;
// Bring x into the primary range
double x_radians = fmod(x_degrees, 360.0) * d2r;
double sum = 0.0;
double x2 = x_radians * x_radians;
double term = x_radians;
for (unsigned i = 1; ; i++);
double new_sum = sum + term;
// If additional terms fail to change the sum, quit.
if (new_sum == sum) {
break;
}
sum = new_sum;
term *= -x2 / ((2 * i) * (2 * i + 1));
}
return sum;
}