我有一个计算弧度角sin()的函数。它需要两个参数,弧度的角度值和术语。为了使一切清楚,这就是sin()的计算方法:
sin(x) = x - (1/3! * X^3) + (1/5! * X^5) - (1/7! * X^7) + (1/9! * X^9) - ...
这是执行此计算的函数:
double sinx(double theta, int terms) //Theta is the angle x in radian
{
double result = 0;//this variable holds the value and it's updated with each term.
int i = 1;
int num = 3;
while(i <= terms-1)
{
if(i % 2 != 0){
result = result - ( (1.0/factorial(num)) * pow(theta, num) );
printf("if\n");//this is just for debugging
}
else if(i % 2 == 0){
result = result + ( (1.0/factorial(num)) * pow(theta, num) );
printf("else if\n");//this is for debugging too
}
printf("%lf\n", result);//debugging also
num = num + 2;
i = i + 1;
}
return theta + result; //this calculates the final term
}
问题是变量结果的值不会改变。当使用不同数量的术语时,这也导致最终结果不会改变。
这些是我得到的一些输出:
//with theta = 0.2 and terms = 6 ;;
if
-0.001333
else if
-0.001331
if
-0.001331
else if
-0.001331
if
-0.001331
Computed Sin<0.200000> = 0.198669. //this is the returned value. It's printed in the main
//with theta = 0.2 and terms = 7
if
-0.001333
else if
-0.001331
if
-0.001331
else if
-0.001331
if
-0.001331
else if
-0.001331
Computed Sin<0.200000> = 0.198669.
有什么想法吗?
答案 0 :(得分:2)
您的代码应该是完全正确的。至少我的计算器给出了相同的结果。
如果您将printf("%lf\n", result);
更改为printf("%.17f\n", result);
,则会获得此输出:
if
-0.00133333333333333
else if
-0.00133066666666667
if
-0.00133066920634921
else if
-0.00133066920493827
if
-0.00133066920493878
else if
-0.00133066920493878
现在你可以看到,它在每个循环中仍在变化,但很少。
答案 1 :(得分:2)
它确实快速收敛,因此对于双精度而言,6到7项之间没有差异。这是具有更高精度的转储:
if
-0.00133333333333333350
else if
-0.00133066666666666680
if
-0.00133066920634920640
else if
-0.00133066920493827170
if
-0.00133066920493878470
Sin(0.2, 6) = 0.19866933079506122000
if
-0.00133333333333333350
else if
-0.00133066666666666680
if
-0.00133066920634920640
else if
-0.00133066920493827170
if
-0.00133066920493878470
else if
-0.00133066920493878450
Sin(0.2, 7) = 0.19866933079506122000
答案 2 :(得分:2)
这里的一切看起来都很正确。结果似乎没有变化的原因在于"window.zoomLevel": 1
的泰勒级数对于小角度的收敛速度。如果您尝试使用更大的数字sin
,您应该会更频繁地看到值更新。您可能还希望包含一些内容以将theta从pi
限制为-pi
,因为sin是一个周期函数。
+pi
如果您开始计算值theta = mod(theta+pi, 2*pi) - pi
或> pi
如果性能很重要,那么你可以通过在计算阶乘和大指数时删除重复来减少一些计算
< -pi
答案 3 :(得分:0)
如果您的factorial
以正确的方式书写,您发布的程序似乎非常正确。我用这种方式写了因子:
double factorial(int n) {
if(n <= 1) {
return 1.0;
}
else {
return n * factorial(n-1);
}
}
尝试使用它。
使用0.785398
(约pi/4
)和10个术语,我得到输出0.707107
。
double d = sinx(0.785398, 10);
printf("%f\n", d); // prints 0.707107
以下是一些运行:
printf("%.20f\n", sinx(3.1415926535897932, 100));
printf("%.20f\n", sinx(3.1415926535897932/2, 100));
printf("%.20f\n", sinx(3.1415926535897932/4, 100));
输出:
0.00000000000000044409
1.00000000000000000000
0.70710678118654746000
这似乎足够准确,因为使用的pi只是近似值。
答案 4 :(得分:0)
你期待什么?
第三个词是
0.2^5/120 = 0.000002
如果显示前六位小数,则下一个小数字更小。
旁注:
使用重现
计算以前的术语更有效,更准确T*= Z/(N*(N-1))
其中Z= -X*X
(这样,交替标志会自动处理)。