积分(二)——复化Simpson(C++)

前言

前言

simpson积分

simpson积分公式
∫ a b f ( x ) d x ≈ b − a 6 [ f ( a ) + f ( b ) + 4 f ( a + b 2 ) ] \int_{a}^{b}f(x)dx \approx \frac{b-a}{6}[f(a)+f(b)+4f(\frac{a+b}{2})] abf(x)dx6ba[f(a)+f(b)+4f(2a+b)]
与梯形积分类似,当区间[a,b]较大时,积分与实际相差较大。

复化simpson积分

假设区间[a,b]被划分为n个小区间,则有区间间隔为 h = b − a n , x k = a + k h ( k = 0 , ⋯   , n ) h=\frac{b-a}{n},x_k=a+kh(k=0,\cdots,n) h=nba,xk=a+kh(k=0,,n),对于每一个小区间都有:
∫ x k x k + 1 f ( x ) d x ≈ h 6 [ f ( x k ) + f ( x k + 1 ) + 4 f ( x k + 1 2 ) ] \int _{x_k}^{x_{k+1}}f(x)dx \approx \frac{h}{6}[f(x_k)+f(x_{k+1})+4f(x_{k+\frac{1}{2}})] xkxk+1f(x)dx6h[f(xk)+f(xk+1)+4f(xk+21)]
在[a,b]区间内进行累加可以得到
∫ a b f ( x ) d x ≈ h 6 [ f ( a ) + f ( b ) + 2 ∑ k = 0 n − 1 f ( x k + 1 ) + 4 ∑ k = 0 n − 1 f ( x k + 1 2 ) ] = S n \int _{a}^{b}f(x)dx \approx \frac{h}{6}[f(a)+f(b)+2\sum_{k=0}^{n-1}f(x_{k+1})+4\sum_{k=0}^{n-1}f(x_{k+\frac{1}{2}})]=S_n abf(x)dx6h[f(a)+f(b)+2k=0n1f(xk+1)+4k=0n1f(xk+21)]=Sn

误差分析

复化simpson积分的余项为: R [ f ] = − b − a 180 ( h 2 ) 4 f ( 4 ) ( ξ ) = − ( b − a ) 5 2880 n 4 f ( 4 ) ( ξ ) R[f]=-\frac{b-a}{180}(\frac{h}{2})^4f^{(4)}(\xi)\\ =-\frac{(b-a)^5}{2880n^4}f^{(4)}(\xi) R[f]=180ba(2h)4f(4)(ξ)=2880n4(ba)5f(4)(ξ)
与梯形积分相似,对其加密一倍n,可以得到对应的事后误差估计公式:
S 2 n ( f ) − s n ( f ) < 15 ϵ S_{2n}(f)-s_n(f)< 15\epsilon S2n(f)sn(f)<15ϵ
可以等价于:
I ( f ) − S 2 n ( f ) < ϵ I(f)-S_{2n}(f)< \epsilon I(f)S2n(f)<ϵ

代码

#include<iostream>
#include<cmath>
#include<iomanip>//这个头文件仅仅是用来设置cout的输出精度
#define abs(x) (x>0?x:-x)
using namespace std;
double Simpson(int n,double a,double b,float(*f)(float x))
{
   
    double f_x=0.0f;
    double h=(b-a)/n;

    for(int i=0;i<n;i++)
    {
   
        f_x+=4*f(a+i*h+h/2);//算f(x_(k+1/2))
    }
    for(int i=1;i<n;i++)
    {
   
        f_x+=2*f(a+i*h);//算f(x_(k+1))
    }
    f_x+=f(a)+f(b);
    f_x=f_x*h/6;
    return f_x;
}
//直接在这里换函数,函数为sin(x)/x
float fx(float x)
{
   
    float result;
    float x_temp=((x==0)?1e-15:x);
    result=sin(x_temp)/x_temp;
    return result;
}
int main()
{
   
    double error=1e-6;//表示误差小于10^-6次方
    double a = 0.0, b = 2.0;
    int n=1;
    double f_x_n=(fx(a)+fx(b))*(b-a)/2;
    double f_x_2n;
    while(true)
    {
   
        f_x_2n=Simpson(n*2,a,b,fx);//算T2n
        if(fabs(f_x_n-f_x_2n)<(error*15))
        {
   
            // cout<<n<<":simposon error="<<fabs(f_x_n-f_x_2n)<<endl;
            // printf("%.8f,%.8f\n",f_x_n,f_x_2n);
            cout << "Simpson积分的误差为:" << fabs(f_x_n - f_x_2n) << endl;
            n*=2;
            break;
        }
        n+=1;
        f_x_n=Simpson(n,a,b,fx);
    }
    cout<<"区间划分数量:n="<<n<<",积分值为:"<<std::setprecision(10)<<f_x_2n<<endl;
    return 0;
}

结果分析

与梯形积分相比,在相同的被积函数和积分区间上,为了达到一样的误差范围,其迭代次数更少:
在这里插入图片描述

使用matlab进行对比可以得到:
在这里插入图片描述
可以看出其实际误差已经达到了期望。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-16 04:38:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-16 04:38:01       101 阅读
  3. 在Django里面运行非项目文件

    2024-02-16 04:38:01       82 阅读
  4. Python语言-面向对象

    2024-02-16 04:38:01       91 阅读

热门阅读

  1. AtCoder Beginner Contest 338(A~E补题)

    2024-02-16 04:38:01       58 阅读
  2. B2092 开关灯

    2024-02-16 04:38:01       58 阅读
  3. CodeForces Round 925 Div.3 A-F 题解

    2024-02-16 04:38:01       45 阅读
  4. 数据结构入门(3)1:顺序表接口实现

    2024-02-16 04:38:01       47 阅读
  5. 蓝桥杯:日期统计讲解(C++)

    2024-02-16 04:38:01       50 阅读
  6. C++11 thread_local

    2024-02-16 04:38:01       56 阅读
  7. 「数据结构」优先级队列

    2024-02-16 04:38:01       56 阅读
  8. 0|1分数规划

    2024-02-16 04:38:01       50 阅读
  9. Pycharm配置运行selenium教程

    2024-02-16 04:38:01       48 阅读
  10. 微服务设计:Spring Cloud 链路追踪概述

    2024-02-16 04:38:01       48 阅读
  11. 代码随想录二刷——二叉树day18

    2024-02-16 04:38:01       60 阅读