• 辛普森积分入门讲解


    辛普森积分

    引用部分

    定义

    辛普森积分法就是在积分区间[a,b]上去找三个点a、b和m=(a+b)/2,计算其原函数的在此处的值,然后用抛物线来拟合原函数。

    正文

    • Simpson积分公式

    用途:来求一个函数的积分的近似值,用于面积计算等精度要求不是特别苛刻的地方。

    其实它就是用一个二次函数曲线不断拟合逼近原函数,然后求得原函数的近似值。


    • 公式说明:

    前置:g(x)为一个关于x的二次函数(抛物线),其中g(x)=A×x2+B×x+C,对于求定积分0xg(x)dx,通过求积得其等于A×x33+B×x22+C×x+D 其中D为常数,可以看做0。令W(x)=0xg(x)dx,所以对于求一段定积分则有abg(x)=W(b)W(a)


    在平面直角坐标系里,由(x1,y1),(x2,y2),(x3,y3)(其中x3=x1+x22)确定的抛物线f(x)在区间[x1,x2]的定积分为:

    x1x2f(x)dx=16×(x2x1)×(y1+y2+4×y3)

    下面给出简单的证明:

    g(x)=A×x2+B×x+C 为拟合后的抛物线,则有

    x1x2f(x)dxx1x2g(x)dx

    =W(x2)W(x1)

    =A3×(x2)3+B2×(x2)2+C×x2(A3×(x1)3+B2×(x1)2+C×x1)

    =A3×((x2)3(x1)3)+B2×((x2)2(x1)2)+C×(x2x1)

    =x2x16×(2×A×((x2)2+x1×x2+(x1)2)+3×B×(x2+x1)+6×C)

    展开化简整理得:
    =x2x16×(A×(x1)2+B×x1+C+A×(x2)2+B×x2+C+4×A×(x2+x12)2)

    将其组合成完全平方式(配方)后
    =x2x16×(g(x1)+g(x2)+4×g(x1+x22))

    =x2x16×(g(x1)+g(x2)+4×g(x3))

    于是我们就得到了simpson积分公式
    abf(x)dxba6×[g(a)+4×g(a+b2)+g(b)]

    在实际计算中g(x)的值可以用原函数f(x)的值来代替,于是就是如下公式:

    abf(x)dxba6×[f(a)+4×f(a+b2)+f(b)]

    代码:

    double simpson(double l,double r){
        return (r-l)*(f(l)+4*f((l+r)/2)+f(r))/6;
    }

    自适应辛普森积分法

    • 那么实际程序该如何实现辛普森积分求积呢?

    我们如果要求abf(x)dx的近似值的话,可以用递归二分区间求解来达到要求精度。
    用如下公式:

    abf(x)dx=amidf(x)dx+midbf(x)dx

    其中mid=a+b2,证明:显然式证明 :)

    但是因为是浮点数(小数),那么递归多少层,在什么时候返回值结束递归呢?
    我们容易知道如果递归到ba<eps的话精度虽然很高,但是时间复杂度太高了,但是如果递归少了,精度又得不到保证,那该如何是好呢?

    • 自适应法

    自适应法,就是让程序根据实际情况决定如何运行执行操作。自己随便下的定义而已

    这里我们就要用自适应法来解决这个问题啦,让程序自己去决定递归层数,而且又保证精度。

    说的很高深,其实很简单。还是比较难吧

    • 自动化控制区间分割的大小。

    实际操作:二分递归,当满足精度就计算返回值,结束递归。

    伪代码:

    function(l,r,eps,ans):
    mid=(l+r)/2;
    lval=左边的值,rval=右边的值;
    if (满足精度) return 答案;
    eps/=2;
    else return 左边递归+右边递归;

    注意,这里的ans表示上一层计算的整个区间的答案,用来和当前这层来判断精度,eps在递归时每次除以2,这是为了消除精度误差叠加效应,当小误差多了就成大误差了,所以每次要缩小精度。

    代码:

    double asr(double l,double r,double eps,double ans){
        double mid=(l+r)/2;
        double lval=simpson(l,mid),rval=simpson(mid,r);
        if(fabs(lval+rval-ans)<=15*eps) return lval+rval+(lval+rval-ans)/15;
        return asr(l,mid,eps/2,lval)+asr(mid,r,eps/2,rval);
    }
    double asme(double a,double b,double eps){
        return asr(a,b,eps,simpson(a,b));
    }

    推荐文章


    代码

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define db double
    using namespace std;
    const db eps=1e-7;
    db a,b,c,d,L,R;
    db f(db x){return (c*x+d)/(a*x+b);}
    db simpson(db l,db r){return (f(l)+f(r)+4*f((l+r)/2))*(r-l)/6;}
    db asr(db l,db r,db exps,db val){
        db mid=(l+r)/2;
        db lval=simpson(l,mid),rval=simpson(mid,r);
        if(fabs(lval+rval-val)<=15*exps){return lval+rval+(lval+rval-val)/15;}
        return asr(l,mid,exps/2,lval)+asr(mid,r,exps/2,rval);
    }
    db asme(db l,db r,db exps){return asr(l,r,exps,simpson(l,r));}
    int main(){
        scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&L,&R);
        printf("%lf
    ",asme(L,R,eps));
        return 0;
    }

    代码

    
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define db double
    using namespace std;
    const db inf=30;
    const db eps=1e-7,zero=1e-10;
    db a;
    db f(db x){return pow(x,a/x-x);}
    db simpson(db l,db r){return (f(l)+f(r)+4*f((l+r)/2))*(r-l)/6;}
    db asr(db l,db r,db exps,db val){
        db mid=(l+r)/2;
        db lval=simpson(l,mid),rval=simpson(mid,r);
        if(fabs(lval+rval-val)<=15*exps) return lval+rval+(lval+rval-val)/15;
        return asr(l,mid,exps/2,lval)+asr(mid,r,exps/2,rval);
    }
    db asme(db l,db r,db exps){return asr(l,r,exps,simpson(l,r));}
    int main(){
        scanf("%lf",&a);
        if(a<0)puts("orz");
        else printf("%.5lf
    ",asme(zero,inf,eps));
        return 0;
    }
    

    这个虽然求的是不定积分但是,不要被吓到了,因为当x大于30左右后,函数值趋近于0,所以可以不计。
    然后当a<0时函数不收敛,所以无解。


    其他题目[NOI2005]月下柠檬树

    • simpson的其他用途:

    和扫描线结合求圆面积并和其他不规则图形面积等。

    【2018.9.7】最近发现的好文章IN

  • 相关阅读:
    Java学习之Jdk配置
    Socket网络模型之Select模型
    c#之初见反射
    c++读取文件夹中的文件
    C#泛型的初步理解
    C#接口简单介绍
    c#类,属性,方法和对象基本介绍
    事件的基本认识
    委托的基本认识
    在Xshell中使用rz命令上传文件出现乱码且文件无法删除的解决办法
  • 原文地址:https://www.cnblogs.com/VictoryCzt/p/10053439.html
Copyright © 2020-2023  润新知