[学习笔记] 自适应辛普森法

用途:求积分。(即曲线下方面积)

理解起来蛮简单的,就是把曲线下方划分为若干矩形,用矩形面积和估算曲线下方面积;而若矩形按 (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;
}
原文地址:https://www.cnblogs.com/lindalee/p/13122381.html