[学习笔记] 自适应辛普森法
用途:求积分。(即曲线下方面积)
理解起来蛮简单的,就是把曲线下方划分为若干矩形,用矩形面积和估算曲线下方面积;而若矩形按 (x) 等距划分则可能出现近似不够好的情况,我们需要在容易近似的地方少划矩形,不容易近似的地方多划些矩形。
函数 (Simps) 计算的是“三点辛普森公式”的值,可以理解成小矩形的面积。
一个重要的判断是
db l=Simps(a,c,fa,fc),r=Simps(c,b,fc,fb),all=Simps(a,b,fa,fb);
if(fabs(l+r-all)<=15*eps) return l+r+(l+r-all)/15.0;
即当这一段很容易近似,那么就不往下递归了,直接返回结果。
洛谷模板题 P4525 【模板】自适应辛普森法1
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define Eps 1e-8
using namespace std;
typedef double db;
db A,B,C,D,L,R;
db F(db x) { return (C*x+D)/(A*x+B); }
db Simps(db a,db b,db fa,db fb){
db c=a+(b-a)/2,fc=F(c);
return (fa+4*fc+fb)*(b-a)/6.0;
}
db asr(db a,db b,db fa,db fb,db eps){
db c=a+(b-a)/2,fc=F(c);
db l=Simps(a,c,fa,fc),r=Simps(c,b,fc,fb),all=Simps(a,b,fa,fb);
if(fabs(l+r-all)<=15*eps) return l+r+(l+r-all)/15.0;
return asr(a,c,fa,fc,eps/2)+asr(c,b,fc,fb,eps/2);
}
db Asr(db a,db b) { return asr(a,b,F(a),F(b),Eps); }
int main()
{
scanf("%lf%lf%lf%lf",&A,&B,&C,&D);
scanf("%lf%lf",&L,&R);
printf("%.6lf
",Asr(L,R));
return 0;
}