Правило Симпсона использует это приближение для оценки определенного интеграла:
Где
и
Таким образом, есть n + 1 равноотстоящие точки выборки x i .
В размещенном коде параметр n
, переданный функции, представляется как число точек, в которых выполняется выборка функции (в то время как в предыдущей формуле n - количество интервалов , это не проблема).
(Постоянное) расстояние между точками рассчитывается правильно
double h = (b - a) / (n - 1);
В то время как l oop используется для суммирования взвешенных вкладов всех точки повторяются от x = a
до точки с асциссой, близкой к b
, но, вероятно, не совсем b
из-за ошибок округления. Это означает, что последнее вычисленное значение f
, f(x_n)
, может немного отличаться от ожидаемого f(b)
.
Это ничто, однако, по сравнению с ошибкой, вызванной тем, что эти окончания точки суммируются внутри l oop с начальным весом 4 , а затем вычитаются после l oop с весом 1 , в то время как все внутренние точки имеют свой вес, переключенный. Фактически, это то, что код вычисляет:
Также, используя
pow(2, i%2 + 1)
Для генерации последовательности 4, 2, 4, 2, ..., 4 - пустая трата с точки зрения эффективности и может добавить (в зависимости от реализации) другие ненужные ошибки округления.
Следующий алгоритм показывает, как получить тот же (фиксированный) результат, без вызова этой библиотечной функции.
template <typename func_type>
double simpson_rule(double a, double b,
int n, // Number of intervals
func_type f)
{
double h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
double sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(a + i * h);
}
double sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(a + i * h);
}
return (f(a) + f(b) + 2 * sum_evens + 4 * sum_odds) * h / 3;
}
Обратите внимание, что для этой функции необходимо передать количество интервалов (например, использовать 10 вместо 11 для получения тех же результатов функции OP), а не количество Очки.
Тестируемый здесь .