이 글에서는 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 등으로 설정하고 구간을 잘게 나눌수록 근사 정확도가 향상됩니다.