C++ И Численные Методы: Приближенное Интегрирование Ньютона-Котеса

Методы Ньютона-Котеса представляет собой набор методов приближенного интегрирования, основанных на:

разделение отрезка интеграции на равные интервалы; аппроксимация подынтегральной функции на выбранных интервалах полиномами; нахождение общей площади получившихся криволинейных трапеций.

В этой статье будут рассмотрены несколько методов Ньютона-Котеса: трапециевидный метод; метод Симпсона; Метод Ромберга.



Трапециевидный метод

Метод трапеций – самый простой из рассмотренных.

В качестве примера возьмем следующий интеграл:

C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Точность аппроксимации зависит от количества N отрезков, на которые разбивается интервал интегрирования.

Таким образом, длина промежутка равна:

C++ и численные методы: приближенное интегрирование Ньютона-Котеса



C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Площадь трапеции можно рассчитать по формуле:

C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Суммируя все вышесказанное, приблизительное значение интеграла вычисляется по формуле:

C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Функция, вычисляющая интеграл методом трапеций, должна принимать 4 параметра:
границы интеграционного сегмента; субинтегральная функция; количество N интервалов разделения.

  
  
   

double trapezoidalIntegral(double a, double b, int n, const std::function<double (double)> &f) { const double width = (b-a)/n; double trapezoidal_integral = 0; for(int step = 0; step < n; step++) { const double x1 = a + step*width; const double x2 = a + (step+1)*width; trapezoidal_integral += 0.5*(x2-x1)*(f(x1) + f(x2)); } return trapezoidal_integral; }



Метод Симпсона

Метод Симпсона заключается в интегрировании интерполяционного полинома второй степени функции f(x) с узлами интерполяции a, b и m = (a+b)/2 - параболы p(x).

Для повышения точности имеет смысл разбить отрезок интегрирования на N равных интервалов (по аналогии с методом трапеций), на каждом из которых применить метод Симпсона.



C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Площадь параболы можно найти, суммируя площади 6 прямоугольников одинаковой ширины.

Высота первого из них должна быть равна f(a), третьего-пятого - f(m), шестого - f(m).

Таким образом, находим аппроксимацию методом Симпсона по формуле:

C++ и численные методы: приближенное интегрирование Ньютона-Котеса



double simpsonIntegral(double a, double b, int n, const std::function<double (double)> &f) { const double width = (b-a)/n; double simpson_integral = 0; for(int step = 0; step < n; step++) { const double x1 = a + step*width; const double x2 = a + (step+1)*width; simpson_integral += (x2-x1)/6.0*(f(x1) + 4.0*f(0.5*(x1+x2)) + f(x2)); } return simpson_integral; }



метод Ромберга

Пусть T(x) — аппроксимация интеграла, полученного методом трапеций с шагом x. Получаем 3 таких приближения, уменьшая размер шага в 2 раза для каждого расчета.



C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Построим теперь параболу, симметричную относительно оси y, проходящую через точки T(1) и T(1/2), чтобы экстраполировать полученные значения для x, стремящегося к 0.

C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Следовательно, каждое слагаемое первого столбца R(n, 0) аппроксимации Ромберга эквивалентно решению, полученному методом трапеций, а каждое решение второго столбца R(n, 1) эквивалентно методу Симпсона.

Таким образом, формулы приближенного интегрирования методом Ромберга имеют вид:

C++ и численные методы: приближенное интегрирование Ньютона-Котеса



C++ и численные методы: приближенное интегрирование Ньютона-Котеса



C++ и численные методы: приближенное интегрирование Ньютона-Котеса

Реализация на С++:

std::vector<std::vector<double>> rombergIntegral(double a, double b, size_t n, const std::function<double (double)> &f) { std::vector<std::vector<double>> romberg_integral(n, std::vector<double>(n)); romberg_integral.front().

front() = trapezoidalIntegral(a, b, 1, f); double h = b-a; for(size_t step = 1; step < n; step++) { h *= 0.5; double trapezoidal_integration = 0; size_t stepEnd = pow(2, step - 1); for(size_t tzStep = 1; tzStep <= stepEnd; tzStep++) { const double deltaX = (2*tzStep - 1)*h; trapezoidal_integration += f(a + deltaX); } romberg_integral[step].

front() = 0.5*romberg_integral[step - 1].

front() + trapezoidal_integration*h; for(size_t rbStep = 1; rbStep <= step; rbStep++) { const double k = pow(4, rbStep); romberg_integral[step][rbStep] = (k*romberg_integral[step][rbStep-1] - romberg_integral[step-1][rbStep-1])/(k-1); } } return romberg_integral; }

Теги: #математика #C++ #математика

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.