我必须计算arctan(x)
的值。我通过评估以下系列计算了这个值:
Arctan(x)= x - x ^ 3/3 + x ^ 5/5 - x ^ 7/7 + x ^ 9/9 - ...
但是下面的代码无法计算实际值。例如,calculate_angle(1)
返回38.34。为什么?
const double DEGREES_PER_RADIAN = 57.296;
double calculate_angle(double x)
{
int power=5,count=3;
double term,result,prev_res;
prev_res = x;
result= x-pow(x,3)/3;
while(abs(result-prev_res)<1e-10)
{
term = pow(x,power)/power;
if(count%2==0)
term = term*(-1);
prev_res=result;
result=result+term;
++count;
power+=2;
// if(count=99)
// break;
}
return result*DEGREES_PER_RADIAN;
}
答案 0 :(得分:3)
stdlib.h
功能abs
所在的位置。您必须忽略有关隐式声明abs
的警告。我检查了删除include会产生结果38.19并包含它会产生结果~45。
当使用未声明的函数(在本例中为abs)时,编译器不需要停止编译。相反,它允许对函数的声明方式做出假设(在这种情况下,是错误的。)
此外,与其他已经说过的海报一样,你使用abs
是不合适的,因为它返回一个int,而不是double或float。 while中的条件应为>1e-100
而不是<1e-100
。 1e-100
也太小了。
-
在计算前两个加数后,您忘记增加count
和power
:
prev_res = x;
result= x-pow(x,3)/3;
count = 4; <<<<<<
power = 5; <<<<<<
while(abs(result-prev_res)<1e-100)
{
term = pow(x,power)/power;
if(count%2==1)
term = term*(-1);
此外,我考虑使用count
变量违反直觉:它与3
初始化,如果它表示最后使用的权力;但是,循环迭代会将其增加1
而不是2
,您可以按count%2 == 1
而不是power%4 == 3
来确定符号
答案 1 :(得分:3)
该系列会聚到tan ^ { - 1} x,但速度不是很快。在x=1
:
1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
在1/9
期间截断时出现的错误是什么?它在1/9
左右。要获得10^{-100}
准确度,您需要10^{100}
个术语。宇宙会在你得到它之前结束。并且,灾难性的舍入错误和截断错误会使答案完全不可靠。 double
s只能使用14位数字。
查看Abramowitz和Stegun [AMS 55]的参考文献或http://dlmf.nist.gov的新NIST数学函数数字图书馆,看看这些是如何在实践中完成的。通常,人们使用Padé近似而不是Taylor系列。即使你坚持使用泰勒系列,你也经常使用切比雪夫近似来减少总误差。
我还推荐Forman Acton的[通常]工作的数值方法。或者......系列中的数字食谱。
答案 2 :(得分:2)
在前两个学期之后你的签名是错误的。它应该是:
if(count%2==0)
term = term*(-1);
在while条件下你的比较是错误的。而且,你期望一种不切实际的高精度。我会建议更像这样的东西:
while(fabs(result-prev_res)>1e-8)
最后,您将获得更准确的结果,并为DEGREES_PER_RADIAN
提供更好的价值。为什么不这样:
const double DEGREES_PER_RADIAN = 180/M_PI;