自適應Simpson積分
阿新 • • 發佈:2020-08-14
用$g(x)=A*x^2+B*x+C$來代替原函式$f(x)$,設$g(x)$原函式為$G(x)$,顯然$G(x)=\frac{1}{3}*A*x^3+\frac{1}{2}*B*x^2+C*x$
$\int_a^b f(x) dx \approx \int_a^b g(x) dx=G(b)-G(a)$
代入化簡得
$$\int_a^b f(x) dx \approx \frac{a-b}{6}*[g(a)+g(b)+4*g(\frac{a+b}{2})]$$
二分割槽間,然後計算區間積分,通過期望容差來控制二分
如果$|S(a,mid)+S(mid,b)-S(a,b)|<15*\varepsilon$,則中止二分,並且認為
$$S(a,b)=S(a,m)+S(m,b)+\frac{S(a,mid)+S(mid,b)-S(a,b)}{15}$$
否則繼續二分
其中$mid=\frac{a+b}{2},\varepsilon為期望容差$
參考部落格:https://www.cnblogs.com/chy-2003/p/11644112.html
例題:
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> usingnamespace std; int T; double a, b, l, r; inline double sqr(double x) { return x * x; } double f(double x) { double t = sqr(b) - sqr(b) / sqr(a) * sqr(x); return 2 * sqrt(t); } double calc(double l, double r) { double mid = (l + r) / 2; return (f(l) + 4 * f(mid) + f(r)) * (r - l) / 6; } double simpson(double l, double r, double eps) { double mid = (l + r) / 2; double st = calc(l, r), sl = calc(l, mid), sr = calc(mid, r); if (fabs(sl + sr - st) <= 15 * eps) return sl + sr + (sl + sr - st) / 15; return simpson(l, mid, eps / 2) + simpson(mid, r, eps / 2); } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); scanf("%d", &T); while (T--) { scanf("%lf%lf%lf%lf", &a, &b, &l, &r); printf("%.3lf\n", simpson(l, r, 1e-6)); } return 0; }