算法笔记-自适应辛普森法
辛普森法(Simpson),是一种求数值积分的方法。
求积分的时候,可以将其分成无穷多个小区间或者用 牛顿-莱布尼茨公式。
如果不能用这两种方法,就有了 数值积分。
辛普森法的核心思想就是把函数
由于把
其中
稍微改写下形式就得到了辛普森公式:
- 辛普森法
有一自然数
对于
代码实现很简单,就不再赘述了。
- 自适应辛普森法
从上文可知,结果的进度取决于
可以对于一段积分先代入辛普森公式求值,然后再将这段积分平分成两段继续求积分,如果差值小于要求的精度
\quad
[模板]自适应辛普森法 1
标准模板,没什么好说的:
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-6;
double a, b, c, d, l, r;
double f(double x) {
return (c * x + d) / (a * x + b);
}
double simpson(double l, double r) {
double mid = (l + r) / 2.0;
return (f(l) + 4.0 * f(mid) + f(r)) * (r - l) / 6.0;
}
double asr(double l, double r, double eps, double ans) {
double mid = (l + r) / 2.0, l_ = simpson(l, mid), r_ = simpson(mid, r);
if (fabs(l_ + r_ - ans) <= 15.0 * eps) return l_ + r_ + (l_ + r_ - ans) / 15.0;
return asr(l, mid, eps / 2.0, l_) + asr(mid, r, eps / 2.0, r_);
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> a >> b >> c >> d >> l >> r;
cout << fixed << setprecision(6) << asr(l, r, eps, simpson(l, r));
return 0;
}
[模板]自适应辛普森法 2
一看,
精度多取两位保险。
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
double a, b, c, d, l, r;
double f(double x) {
return pow(x, (a / x) - x);
}
double simpson(double l, double r) {
double mid = (l + r) / 2.0;
return (f(l) + 4.0 * f(mid) + f(r)) * (r - l) / 6.0;
}
double asr(double l, double r, double eps, double ans) {
double mid = (l + r) / 2.0, l_ = simpson(l, mid), r_ = simpson(mid, r);
if (fabs(l_ + r_ - ans) <= 15.0 * eps) return l_ + r_ + (l_ + r_ - ans) / 15.0;
return asr(l, mid, eps / 2.0, l_) + asr(mid, r, eps / 2.0, r_);
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> a;
if (a < 0) return cout << "orz", 0;
cout << fixed << setprecision(5) << asr(eps, 15.0, eps, simpson(l, r));
return 0;
}