模板 - 自适应辛普森法积分
经过模板验证,6位精度取8位或9位还是比较快的。
一道练习题?https://www.luogu.org/problemnew/show/UVA11346
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
namespace Adaptive_Simpson_Integral {
/* 备注:
1.直接往上面模板的F函数中输入本题给定函数,然后调用一次asr(l,r)即可。
2.可能需要修改精度要求,测试过至少取需求精度的100倍或1000倍就挺好。
*/
double seps=1e-9;
double a,b,c,d;
void init(double _seps,double _a,double _b,double _c,double _d){
seps=_seps,a=_a,b=_b,c=_c,d=_d;
}
double F(double x) {
//需要积分的函数
return (c*x+d)/(a*x+b);
}
double simpson(double l,double r) {
double mid=(l+r)/2;
return (F(l)+4*F(mid)+F(r))*(r-l)/6;
}
double asr(double l,double r,double A) {
double mid=(l+r)/2;
double L=simpson(l,mid),R=simpson(mid,r);
if(fabs(L+R-A)<=15*seps)
return L+R+(L+R-A)/15.0;
return asr(l,mid,L)+asr(mid,r,R);
}
double asr(double l,double r) {
return asr(l,r,simpson(l,r));
}
/* 备注:
1.直接往上面模板的F函数中输入本题给定函数,然后调用一次asr(l,r)即可。
2.可能需要修改精度要求,测试过至少取需求精度的100倍或1000倍就挺好。
*/
}
using namespace Adaptive_Simpson_Integral;
int main() {
double a,b,c,d,L,R;
scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&L,&R);
init(1e-8,a,b,c,d);
printf("%.6f\n",asr(L,R));
}
传入函数指针的自适应辛普森法积分
当有多个要积分的函数时,可以这样写:
double A,B,C,D,E;
namespace Adaptive_Simpson_Integral {
/* 备注:
1.直接往上面模板的f函数中输入本题给定函数,然后调用一次asr(l,r)即可。
2.可能需要修改精度要求,测试过至少取需求精度的100倍或1000倍就挺好。
*/
double seps=1e-8;
double f(double x) {
//需要积分的函数
return A*x*x+B*x+C;
}
double g(double x) {
//需要积分的函数
return D*x+E;
}
double simpson(double l,double r,double (*F)(double)) {
double mid=(l+r)/2;
return (F(l)+4*F(mid)+F(r))*(r-l)/6;
}
double asr(double l,double r,double A,double (*F)(double)) {
double mid=(l+r)/2;
double L=simpson(l,mid,F),R=simpson(mid,r,F);
if(fabs(L+R-A)<=15*seps)
return L+R+(L+R-A)/15.0;
return asr(l,mid,L,F)+asr(mid,r,R,F);
}
double asr(double l,double r,double (*F)(double)) {
return asr(l,r,simpson(l,r,F),F);
}
/* 备注:
1.直接往上面模板的F函数中输入本题给定函数,然后调用一次asr(l,r)即可。
2.可能需要修改精度要求,测试过至少取需求精度的100倍或1000倍就挺好。
*/
}
using namespace Adaptive_Simpson_Integral;