Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 구현하는 심슨 3/8 법칙: 정적분 수치 근사의 원리와 코드 예제

이 글에서는 C++를 이용해 심슨 3/8 법칙(Simpson's ⅜ Rule)을 구현하는 방법을 알아보겠습니다.

심슨 3/8 법칙이란?

심슨 3/8 법칙은 수치 적분(numerical integration) 기법의 하나로, 해석적으로 구하기 어려운 정적분의 값을 수치적으로 근사할 때 널리 사용됩니다. 이름 그대로 최종 결과에 구간 폭의 3/8배라는 계수가 곱해지는 것이 특징입니다.

흔히 알려진 심슨 1/3 법칙이 포물선(이차 다항식)으로 곡선을 근사하는 것과 달리, 3/8 법칙은 각 부분 구간을 삼차 다항식(cubic polynomial)으로 근사하기 때문에 곡률이 큰 함수에서도 비교적 안정적인 결과를 보여줍니다.

동작 원리와 계수 패턴

심슨 3/8 법칙을 적용하려면 적분 구간을 3의 배수 개수로 나누는 것이 이상적입니다. 구간을 n등분했을 때 각 분점의 함수값에 다음과 같은 계수를 곱해 모두 더합니다.

  • 양 끝점(x₀, xₙ): × 1
  • 인덱스가 3의 배수인 내부 분점: × 2
  • 나머지 내부 분점: × 3

즉, 계수는 1, 3, 3, 2, 3, 3, 2, …, 3, 3, 1의 패턴을 따르며, 최종 근사값은 다음 공식으로 계산됩니다.

ab f(x)dx ≈ (3h / 8) × [f(x₀) + 3·f(x₁) + 3·f(x₂) + 2·f(x₃) + … + f(xₙ)] , 단 h = (b − a) / n

C++ 구현 예제

아래 예제는 f(x) = 1/(1+x²) 함수를 구간 [1, 8]에서 근사하는 코드입니다.

#include<iostream>
using namespace std;

// 적분할 함수 f(x) = 1 / (1 + x^2)
float func_inte(float x){
    return (1 / (1 + x * x));
}

// 심슨 3/8 법칙으로 근사값 계산
float func_calculate(float lower_limit, float upper_limit, int interval_limit){
    float value;
    // 구간 폭(h) 계산
    float interval_size = (upper_limit - lower_limit) / interval_limit;
    // 양 끝점의 함수값을 합에 추가 (계수 1)
    float sum = func_inte(lower_limit) + func_inte(upper_limit);
    for (int i = 1 ; i < interval_limit ; i++) {
        if (i % 3 == 0)
            sum = sum + 2 * func_inte(lower_limit + i * interval_size); // 계수 2
        else
            sum = sum + 3 * func_inte(lower_limit + i * interval_size); // 계수 3
    }
    return ( 3 * interval_size / 8 ) * sum;
}

int main(){
    int interval_limit = 8;
    float lower_limit = 1;
    float upper_limit = 8;
    float integral_res = func_calculate(lower_limit, upper_limit, interval_limit);
    cout << integral_res << endl;
    return 0;
}

실행 결과

0.663129

코드 설명

  • func_inte(): 적분 대상 함수 f(x) = 1/(1+x²)를 정의합니다.
  • func_calculate(): 먼저 구간 폭 h를 구하고, 양 끝점의 함수값을 합에 더한 뒤 내부 분점을 순회합니다. 인덱스가 3의 배수이면 2를, 그렇지 않으면 3을 곱해 누적하며, 마지막에 (3h/8)을 곱해 최종 근사값을 반환합니다.
  • main(): 구간 [1, 8]을 8개의 소구간으로 나누어 계산한 결과를 출력합니다.

정확도에 대한 참고 사항

f(x) = 1/(1+x²)의 실제 적분값은 arctan(8) − arctan(1) ≈ 0.66104로, 프로그램의 결과인 0.663129와 약간의 오차가 있습니다. 또한 엄밀한 심슨 3/8 법칙을 적용하려면 구간 수가 3의 배수여야 하므로, 실무에서는 구간 수를 6, 9, 12 등으로 설정하고 구간을 잘게 나눌수록 근사 정확도가 향상됩니다.