2011-10-09 6 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; 
} 

를 I는 미세 적분 근사있다 :이 때까지 소정 기간의 부분 감소를 통해 근사치를 합산하여 적응된다

//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

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 integrate(double (*f)(double x), double a, double b, double tol) 
{ 
    return trap(f, a, b, tol, 1); 
} 
,691,363 : 당신이 currentLevel를 지정하지 않아도
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)); 
    } 
} 

당신은 도우미 기능을 추가 할 수 있습니다210

내가 이것을 integrate(square, 0, 2, 0.01)이라고하면 나는 2.6875의 답을 얻을 수있다. 이는 정확한 결과 인 8/3 = 2.6666...7에 수렴하기 위해 더 낮은 허용 오차가 필요하다는 것을 의미한다. Simpson's method에 대한 오류 조항을 사용하여 이에 대한 정확한 오류 제 한을 확인할 수 있습니다.

+0

나는 본다. 간격 계산에 대한 어리석은 수학 실수. 왜 전역 변수를 증가시키는 것이 나쁜가? 그것은 같은 효과를 낼 것 같습니다. 당신의 도움을 주셔서 대단히 감사합니다. –

+0

나는 currentLevel이 전역 변수가 될 필요가없는 도우미 함수를 사용하는 것이 도움이된다는 것을 알았다. 이제는 올바른 값으로 수렴했습니다. 그러나 이것이 왜 도움이되었는지 이해할 수 없습니다. –

+0

이제 왜 currentLevel을 전역 변수로 사용하지 않는지 이해합니다. 전역 변수로 사용하면 적응 알고리즘의 개념적 목적을 완전히 상실 할 수 있습니다.함수의 재귀 수준에 의존해야합니다. 감사. –