数值方法求积分 详解+模板代码

20 篇文章 1 订阅

什么是数值积分

  数值积分可以用来求定积分的近似值。对于很多函数来说,我们是可以使用初等函数来表示出其积分的,对于这种函数,只需要求出不定积分然后代入值就能得到定积分了。

  可是除此之外还有许多难求的函数和没法使用初等函数表示的函数。当我们想要求出它们的定积分的时候,需要使用数值积分来求解。

  在ACM中一些题目需要使用数值积分来求解,以下列出一些求数值积分的方法,由简单到难,而对ACMer来说最重要的是复合Simpson,其精度较高,且可调精度,是乱搞积分几何的利器

  我从这学的:网易公开课 MIT 数值积分

  学习的契机是想要A掉这题:ZOJ 3898 我的题解

法一·黎曼和

黎曼和是用将区间等长分为 n 段,然后用矩形去逼近函数,每段的长为 Δx

可以选择每段左侧的函数值作为矩形的高,也可以选择每段右侧的函数值作为矩形的高。

这里写图片描述

若设 n+1 个函数值从左至右为 x0,x1xn ,可得如下公式: 

Left Hand Riemann=Right Hand Riemann=Δxf(x0)+Δxf(x1)++Δxf(xn1)=Δxi=0n1f(xi)Δxf(x1)+Δxf(x2)++Δxf(xn)=Δxi=1nf(xi)
这种逼近比较粗糙,不过能比较好地传达数值积分的概念。

法二·梯形法

黎曼和虽然简单,但是精度堪忧,没法很好地模拟逼近函数,接下来介绍第二种方法。

可以看出用矩形逼近的时候有很多空缺,使用梯形去逼近,就能大大提高精度了,看上去很像了。 
这里写图片描述 
沿用之前的 xi ,由梯形公式我们可以得到如下公式: 

Trapezoid=Δx(f(x0)+f(x1))2+Δx(f(x1)+f(x2))2++Δx(f(xn1)+f(xn))2=Δx(f(x0)2+f(x1)++f(xn1)+f(xn)2)=Left Hand Riemann+Right Hand Riemann2

可以看出梯形法求出的就是左右黎曼和的平均值。

公式中第一个和最后一个需要除以 2 其他都能合出来 1 个。

法三·Simpson公式

前两种都比较简单,但是精度比较差,第三种方法是用抛物线去逼近

其实我并不知道是怎么计算的,是从公开课上学来的。

使用 Simpson 公式首先需要 n 为偶数。

将整个区间分为 n2 段,每段的底为 2Δx ,高比较难搞,但是是有公式的: Simpson height=f(xl)+4f(xm)+f(xr)6

于是有公式: 

Simpson=Δx3(f(x0)+4f(x1)+2f(x2)++2f(xn2)+4f(xn1)+f(xn))

这里写图片描述

法四·复合Simpson

Simpson 公式的精度其实已经相当不错了,可是相对于ACM中所需的精度仍然有差距

为了提高精度,我们需要多次重复利用 Simpson 公式。

我们先定义被积函数为 f(x) ,定义 Simpson(l,r)=(rl)f(l)+4f(l+r2)+f(r)6

这也就是常规的 Simpson 公式,再定义函数 RSimpson 为复合 Simpson

当我们要求 RSimpson(l,r) ,先令 m=l+r2

Simpson(l,r)Simpson(l,m)+Simpson(m,r) 时我们就认为精度够了返回其中一个。

当不满足的时候我们就再分段去求 RSimpson(l,m)+RSimpson(m,r)

这样得到的精度就比较高了,而且通过定义 的范围可以调整精度。

总结公式如下: 

RSimpson(l,r)={Simpson(l,r)                                              approximateRSimpson(l,m)+RSimpson(m,r)       else

复合Simpson的实现

inline double getAppr(double fl, double fm, double fr, double l, double r) {
    return (fl+4*fm+fr)*(r-l)/6.0;
}

double Simpson(double l, double r, double fl, double fr) {
    double m = (l+r)/2, lm = (l+m)/2, rm = (r+m)/2;
    double fm = f(m), flm = f(lm), frm = f(rm);
    double vlr = getAppr(fl, fm, fr, l, r);
    double vlm = getAppr(fl, flm, fm, l, m);
    double vrm = getAppr(fm, frm, fr, m, r);
    return fabs(vlr-vlm-vrm) < EPS ? vlr : Simpson(l, m, fl, fm)+Simpson(m, r, fm, fr);
}

复合Simpson的实现2(Natureal的代码)

inline double getAppr(double l,double r){
    return (f(l) + 4.0*f((l+r)/2) + f(r)) * (r - l) / 6.0;
}

double Simpson(double l,double r){
    double sum = getAppr(l,r);
    double mid = (l+r)/2;
    double suml = getAppr(l,mid);
    double sumr = getAppr(mid,r);
    return (fabs(sum - suml - sumr) < EPS) ? sum : Simpson(l, mid) + Simpson(mid, r);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值