1

我需要大约 (1-x)^0.25 并具有给定的精度(例如 0.0001)。我正在使用Wikipedia 上的扩展(1+x)^0.25。当当前表达式小于精度时,我需要停止近似。

long double s(long double x, long double d) {
    long double w = 1;
    long double n = 1; // nth expression in series
    long double tmp = 1;

    // sum while last expression is greater than accuracy
    while (fabsl(tmp) >= d) {
        tmp *= (1.25 / n - 1) * (-x); // the next expression
        w += tmp; // is added to approximation
        n++; 
    } 

    return w;
}

不要介意长双n。:P 当我不检查当前表达式的值但计算 1000 个或更多表达式时,这很有效。该函数的域是 <-1;1> 并且 s() 可以很好地计算 <-1;~0.6> 中 x 的近似值。参数越大,计算的误差越大。从 0.6 开始,它超过了准确度。

我不确定问题是否足够清楚,因为我不太了解英语数学语言。问题是 while 条件有什么问题以及为什么函数 s() 不能正确近似。

编辑: 问题基本解决了。当 x>0 时,我必须从 1 中减去连续表达式的绝对值。

if (x<0)
   w += tmp;
else
   w -= fabsl(tmp);

在那之后准确性增加了很多(当然是狐狸x> 0)。冗余误差源于长期的双重误差。就这样。无论如何,谢谢你们。

4

2 回答 2

1

尝试绘制函数图

abs((1.0+x) alpha - binomial_formula(alpha,x,tolerance))
即使在诸如 [-0.5;0.5] 这样的近距离 x 范围内,您也会得到类似的结果: 在此处输入图像描述

这意味着您的二项式展开实现是不稳定的。随着 x 离零越来越远 - 系列必须包含越来越多的给定精度的项。但是在当前的扩展实现中这样做会导致发生灾难性取消(一些浮点错误累积机制)。尝试阅读我给出的关于如何设计数值稳定算法的链接。

顺便说一句,感谢真正有趣的问题!

于 2011-03-17T15:58:55.760 回答
1

您的问题是,虽然您的算法的迭代部分很好,但终止不是您认为的那样。

您使用的泰勒级数展开在计算无限和时是精确的。但是,您无法评估该无限和并且正在截断。

我想你假设当tmp变得小于你想要的公差时,那么误差w也小于那个公差。

然而,事实并非如此。每次迭代的误差是剩余项的无限和。它是您要丢弃的无数项的总和。其中第一个,即tmp终止点的值,可能小于您的容忍度,但它们的总和可能大于您的容忍度。

当 (-x) 为负时,您碰巧侥幸逃脱,因为交替符号对tmp您有利。x当 (-x) 为正时,当它接近于零时,你就可以侥幸逃脱。

但是,我不相信有一种简单的方法可以提出一个简单的通用停止标准。您必须能够对要丢弃的条款进行一些限制。这现在变成了一个数学问题,而不是一个编程问题。

于 2011-03-17T17:09:35.160 回答