在C ++中不使用epsilon来计算算术几何平均值

时间:2017-10-07 07:47:36

标签: c++ algorithm math mean

是否可以在不使用C ++中的epsilon的情况下计算算术几何平均值?

这是我的代码:

double agm(double a, double b)
{
    if(a > b)
    {
        a = a + b;
        b = a - b;
        a = a - b;
    }

    double aCurrent(a), bCurrent(b),
        aNext(a), bNext(b);

    while(aCurrent - bCurrent != 0)
    {
        aNext = sqrt(aCurrent*bCurrent);
        bNext = (aCurrent+bCurrent)*0.5;
        aCurrent = aNext;
        bCurrent = bNext;
    }

    return aCurrent;
}

double sqrt(double x)
{
    double res(x * 0.5); 

    do
    {
        res = (res + x/res) * 0.5;
    } while(abs(res*res - x) > 1.0e-9);

    return res;
}

它会永远运行。

实际上我很清楚我在问什么。只是你从来没有遇到过这个问题,也许懒得思考它,并立即说没有什么可说的。

所以,这是我正在寻找的解决方案:

我们可以添加以下条件

,而不是eps
if(aCurrent <= aPrev || bPrev <= bCurrent || bCurrent <= aCurrent )

如果条件为真,则意味着我们在机器上以尽可能高的精度计算了算术几何平均值。如您所见,没有eps

在问题和答案中使用eps意味着比较我们说当两个双数之间的差异小于eps时两个双数相等。

请重新考虑打开这个问题。

2 个答案:

答案 0 :(得分:3)

当然可以。在任何情况下,将迭代次数限制为收敛所需的最大值就足够了,这应该接近浮点表示中有效位数的对数。

同样的推理适用于平方根。 (基于浮点指数的良好起始近似,即距离精确根最多2倍,5次迭代总是足以用于双精度)。

作为旁注,请避免使用绝对容差。浮点值可以在很宽的范围内变化。它们可能很大,相比之下,公差为0,或者非常小,以至于它们低于公差本身。优选相对容差,并且没有对0的相对容差的额外困难。

答案 1 :(得分:1)

不,不使用epsilon是不可能的。浮点算法是实数算术的近似值,通常会产生舍入误差。因此,用于计算AGM的两个计算序列不太可能会收敛到完全相同的浮点数。因此,不是测试两个浮点数是否相等,而是需要测试它们是否彼此足够接近以认为它们实际上是相等的。这是通过计算差异并测试它是否真的很小来完成的。

您可以使用硬编码的epsilon值,也可以相对于数字的大小计算它。后者往往更好,因为它允许您使用不同的数字量表。例如。你不应该使用相同的epsilon来尝试计算123450.000012345的平方根; 0.01可能适用于大量数字,但对于较小的数字,您需要0.000001之类的内容。

请参阅What every programmer should know about floating point