-2

我必须计算 的值arctan(x)。我通过评估以下系列计算了这个值:

反正切 (x) = x – x^3/3 + x^5/5 – x^7/7 + x^9/9 - ...</p>

但是下面的代码无法计算出实际值。例如,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;
}
4

3 回答 3

3

编辑:我找到了罪魁祸首。您忘记包含stdlib.h函数abs所在的位置。您一定忽略了关于abs被隐式声明的警告。我检查了删除包含会产生结果 38.19 并包含它会产生结果 ~45。

当使用未声明的函数(在本例中为 abs)时,编译器不需要停止编译。相反,它允许对函数的声明方式做出假设(在这种情况下,错误的假设。)

此外,就像其他海报已经说明的那样,您的使用abs是不合适的,因为它返回一个 int,而不是 double 或 float。while 中的条件应该是>1e-100not <1e-1001e-100也太小了。

--

你忘了增加countpower计算前两个加法后:

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如果它表示最后使用的功率,则用 like 初始化;但是然后,循环迭代将其增加1而不是2并且您决定符号count%2 == 1而不是power%4 == 3

于 2013-05-03T05:42:40.117 回答
3

该系列收敛到 tan^{-1} x,但不是很快。在以下情况下考虑系列x=1

1 - 1/3 + 1/5 - 1/7 + 1/9 - ...

截断1/9术语时的错误是什么?就在身边1/9。为了获得10^{-100}准确性,您需要有10^{100}条款。宇宙会在你得到它之前结束。而且,灾难性的舍入误差和截断误差会使答案完全不可靠。对于 s,您只有 14 位数字可玩double

查看 Abramowitz 和 Stegun [AMS 55] 等参考作品或http://dlmf.nist.gov上的新 NIST 数学函数数字图书馆,了解这些是如何在实践中完成的。通常,使用 Padé 近似值而不是泰勒级数。即使您坚持使用泰勒级数,您也经常使用切比雪夫近似来减少总误差。

我还推荐 [通常] 工作的数值方法,作者是 Forman Acton。或...系列中的数字食谱。

于 2013-05-03T05:45:00.047 回答
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;
于 2013-05-03T05:59:08.200 回答