Інтегрування за формулою Сімпсона
Ми збираємося обчислити значення визначеного інтеграла
Описаний тут розв'язок було опубліковано в одній із дисертацій Томаса Сімпсона у 1743 році.
- Підінтегральну функцію важко або неможливо проінтегрувати аналітично, тож потрібне чисельне наближення? (якщо первісну легко взяти аналітично — інтегруйте напряму, без чисельного методу)
- Функцію можна обчислити в довільній точці відрізка , а сам достатньо гладкий (мала четверта похідна)?
- Шукаєте площу / визначений інтеграл, а не корінь чи екстремум функції? (для кореня → Метод Ньютона, для екстремуму → Тернарний пошук)
Формула Сімпсона
Нехай — деяке натуральне число. Розіб'ємо відрізок інтегрування на рівних частин:
Тепер обчислимо інтеграл окремо на кожному з відрізків , , а потім додамо всі значення.
Отже, припустимо, що ми розглядаємо черговий відрізок . Замінимо на ньому функцію параболою , що проходить через 3 точки . Така парабола завжди існує і єдина; її можна знайти аналітично. Наприклад, ми могли б побудувати її за допомогою інтерполяційного многочлена Лагранжа. Єдине, що залишається зробити, — проінтегрувати цей многочлен. Якщо зробити це для загальної функції , ми отримаємо напрочуд простий вираз:
Додавши ці значення по всіх відрізках, ми отримуємо остаточну формулу Сімпсона:
Похибка
Похибка наближення інтеграла за формулою Сімпсона дорівнює
де — деяке число між і .
Похибка асимптотично пропорційна . Однак наведені вище викладки наводять на думку про похибку, пропорційну . Формула Сімпсона набуває додаткового порядку, оскільки точки, у яких обчислюється підінтегральна функція, розподілені симетрично на відрізку .
Реалізація
Тут — деяка визначена користувачем функція.
- C++
- Python
- TypeScript
- Go
const int N = 1000 * 1000; // кількість кроків (уже помножена на 2)
double simpson_integration(double a, double b){
double h = (b - a) / N;
double s = f(a) + f(b); // a = x_0 і b = x_2n
for (int i = 1; i <= N - 1; ++i) { // дивіться остаточну формулу Сімпсона
double x = a + h * i;
s += f(x) * ((i & 1) ? 4 : 2);
}
s *= h / 3;
return s;
}
N = 1000 * 1000 # кількість кроків (уже помножена на 2)
def simpson_integration(a: float, b: float) -> float:
h = (b - a) / N
s = f(a) + f(b) # a = x_0 і b = x_2n
for i in range(1, N): # дивіться остаточну формулу Сімпсона
x = a + h * i
s += f(x) * (4 if i & 1 else 2)
s *= h / 3
return s
const N = 1000 * 1000; // кількість кроків (уже помножена на 2)
function simpsonIntegration(a: number, b: number): number {
const h = (b - a) / N;
let s = f(a) + f(b); // a = x_0 і b = x_2n
for (let i = 1; i <= N - 1; ++i) { // дивіться остаточну формулу Сімпсона
const x = a + h * i;
s += f(x) * ((i & 1) ? 4 : 2);
}
s *= h / 3;
return s;
}
const N = 1000 * 1000 // кількість кроків (уже помножена на 2)
func simpsonIntegration(a, b float64) float64 {
h := (b - a) / N
s := f(a) + f(b) // a = x_0 і b = x_2n
for i := 1; i <= N-1; i++ { // дивіться остаточну формулу Сімпсона
x := a + h*float64(i)
if i&1 == 1 {
s += f(x) * 4
} else {
s += f(x) * 2
}
}
s *= h / 3
return s
}