辛普森积分法

定积分#

函数 f(x) 在区间 [l,r] 上的定积分 lrf(x)dx 指的是 f(x) 在区间 [l,r] 内与 x 轴所围成的区域的面积(x轴上方为正,下方为负)。

我们需要一种高效的求解这种积分的近似值的方法,于是就有了辛普森积分法

普通辛普森法#

辛普森法的基本思想是将求解区间分成若干段,每一段都使用二次函数的积分公式来进行求解。

二次函数积分公式(辛普森公式):

对于一个二次函数f(x)=Ax2+Bx+C,有

lrf(x)dx=(rl)(f(l)+f(r)+4f(l+r2))6

证(from OI-Wiki):

求积分可得

F(x)=0xf(x)dx=a3x3+b2x2+cx+D

那么则有

lrf(x)dx=F(r)F(l)=a3(r3l3)+b2(r2l2)+c(rl)=(rl)(a3(l2+r2+lr)+b2(l+r)+c)=rl6(2al2+2ar2+2alr+3bl+3br+6c)=rl6((al2+bl+c)+(ar2+br+c)+4(a(l+r2)2+b(l+r2)+c))=rl6(f(l)+f(r)+4f(l+r2))

然后我们通过套公式就可以写出这样一段代码:

double simpson(double l, double r) {
    const double mid = (l + r) / 2;
    return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6; //f(x)为待求解的函数
}

自适应辛普森#

普通的辛普森积分法为了保证精度,在时间效率上会很大地受到区间的限制。

问题在于:区间少了精度不够,区间多了又太慢。

自适应辛普森做到了自动控制拆分区间的大小

double asr(double l, double r, double eps, double ans) {
    const double mid = (l + r) / 2;
    const double fl = simpson(l, mid), fr = simpson(mid, r);
    if (abs(fl + fr - ans) <= 15 * eps)
        return fl + fr + (fl + fr - ans) / 15;
    return asr(l, mid, eps / 2, fl) + asr(mid, r, eps / 2, fr);
}

到了这里,你就可以去做 Luogu P4525 【模板】自适应辛普森法1了!

posted @   LewisLi  阅读(3185)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩