积分逼近函数的递推

时间:2011-10-09 16:57:10

标签: c++ math

我试图使用自适应梯形法则来近似积分。

我有一个粗积分近似值:

//Approximates the integral of f across the interval [a,b]
double coarse_app(double(*f)(double x), double a, double b) {
    return (b - a) * (f(a) + f(b)) / 2.0;
}

我有一个很好的积分近似值:

//Approximates the integral of f across the interval [a,b]
double fine_app(double(*f)(double x), double a, double b) {
    double m = (a + b) / 2.0;
    return (b - a) / 4.0 * (f(a) + 2.0 * f(m) + f(b));
}

通过对给定间隔的递减部分的近似求和,直到递归电平太高或者粗略和精细近似彼此非常接近来使其自适应:

//Adaptively approximates the integral of f across the interval [a,b] with
//    tolerance tol.
double trap(double(*f)(double x), double a, double b, double tol) {
    double q = fine_app(f, a, b);
    double r = coarse_app(f, a, b);
    if ((currentLevel >= minLevel) && (abs(q - r) <= 3.0 * tol)) {
        return q;
    } else if (currentLevel >= maxLevel) {
        return q;
    } else {
        ++currentLevel;
        return (trap(f, a, b / 2.0, tol / 2.0) + trap(f, a + (b / 2.0), b, tol / 2.0));
    }
}

如果我通过将积分分成多个部分并使用fine_app来手动计算积分,我会得到一个很好的近似值。但是,当我使用陷阱功能时,我应该这样做,我的所有结果都太小了。

例如,trap(square,0,2.0,1.0e-2)给出输出0.0424107,其中square函数定义为x ^ 2。但是,输出应该在2.667左右。这比在整个时间间隔内执行一次fine_app更糟糕,它给出的值为3.

从概念上讲,我相信我已经正确实现了它,但是有一些关于C ++递归的东西没有按照我的预期进行。

首次使用C ++进行编程,因此欢迎所有改进。

1 个答案:

答案 0 :(得分:2)

我假设你在其他地方定义了currentLevel。你不想那样做。您还错误地计算了中点。

取a = 3,b = 5:

[a, b / 2.0] = [3, 2.5]
[a + b / 2.0, b] = 2.5, 3]

正确的点应该是[3,4]和[4,5]

代码应如下所示:

double trap(double(*f)(double x), double a, double b, double tol, int currentLevel) {
    double q = fine_app(f, a, b);
    double r = coarse_app(f, a, b);
    if ((currentLevel >= minLevel) && (abs(q - r) <= 3.0 * tol)) {
        return q;
    } else if (currentLevel >= maxLevel) {
        return q;
    } else {
        ++currentLevel;
        return (trap(f, a, (a + b) / 2.0, tol / 2, currentLevel) + trap(f, (a + b) / 2.0, b, tol / 2, currentLevel));
    }
}

您可以添加辅助函数,因此您不必指定currentLevel:

 double integrate(double (*f)(double x), double a, double b, double tol)
 {
     return trap(f, a, b, tol, 1);
 }

如果我将其称为integrate(square, 0, 2, 0.01),我会得到2.6875的答案,这意味着您需要更低的容差才能收敛到8/3 = 2.6666...7的正确结果。您可以使用Simpson's method的错误术语检查确切的错误限制。