2011-10-09 85 views
2

我正在嘗試使用自適應梯形法則來逼近積分。遞歸積分逼近函數

我有一個粗積分近似:

//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,我可以得到一個非常好的近似值。但是,當我使用陷阱函數時,我應該這樣做,所有的結果都太小了。

例如,陷阱(square,0,2.0,1.0e-2)給出0.0424107的輸出,其中平方函數定義爲x^2。不過,產量應該在2.667左右。這比在整個時間間隔內執行fine_app的單次運行要差得多,它的值爲3.

從概念上講,我相信我已經正確實現了它,但是有一些關於C++遞歸的問題,期待它。

首次使用C++編程,所以所有的改進都是值得歡迎的。

+1

currentLevel定義在哪裏?我在你的代碼中看不到它。如果它是一個全局變量,那麼你做錯了什麼。 –

+0

是的,我將currentLevel定義爲全局變量。謝謝你的回答,下面。我會更徹底地審視它。 –

回答

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的錯誤條款檢查確切的錯誤。

+0

我明白了。愚蠢的數學錯誤計算間隔。爲什麼增加一個全局變量是不好的?看起來它會產生同樣的效果。非常感謝您的幫助。 –

+0

我看到,使用幫助函數,使我不需要currentLevel成爲一個全局變量已經有所幫助。它現在收斂在正確的價值,但是,我不明白爲什麼這有助於。 –

+0

我現在明白了爲什麼我不想將currentLevel作爲全局變量。把它作爲一個全局變量完全違背了自適應算法的概念目的。我需要它依賴於函數遞歸的當前級別。謝謝。 –