自适应辛普森积分
1.算法分析
对于式子 ∫ a b f ( x ) d x \int_a^b f(x) {\rm d}x ∫abf(x)dx,如果这个式子很难直接积分的话,可以使用 辛普森积分 方法计算。
它是按照二次函数进行你和,设 f ( x ) = A x 2 + B x + C f(x) = Ax^2 + Bx + C f(x)=Ax2+Bx+C
然后推到后近似为:
∫ a b f ( x ) d x = ( b − a ) ( f ( a ) + f ( b ) + 4 ∗ f ( a + b 2 ) ) 6 \int_a^b f(x) {\rm d}x = \frac{(b - a)(f(a) + f(b) + 4 * f(\frac{a+b}{2}))}{6} ∫abf(x)dx=6(b−a)(f(a)+f(b)+4∗f(2a+b))
如果b - a越小,那么得到的答案就越精确。
但是这不一定精确,因此使用分治的方法进行不断逼近,将a ~ b划分为a ~ mid, mid ~ b,如果其中一段精度不够,那么就递归往下继续运算,直到精度够为止。这个方法叫做 自适应辛普森积分
2.模板
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-12; // 可以接受的精度
double f(double x) {
// 辛普森积分近似模拟的函数f
return sin(x) / x;
}
double simpson(double l, double r) {
// 辛普森积分模板函数,这里模拟二次函数
auto mid = (l + r) / 2;
return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;
}
double solve(double l, double r, double s) {
// 计算从l ~ r的s的积分
auto mid = (l + r) / 2;
auto left = simpson(l, mid), right = simpson(mid, r); // 计算左右边的辛普森积分
if (fabs(left + right - s) < eps) return left + right; // 如果处于精度范围内,直接返回
return solve(l, mid, left) + solve(mid, r, right); // 否则递归往下求解
}
int main() {
double l, r;
scanf<