首页 > 其他分享 >自适应辛普森法 学习笔记

自适应辛普森法 学习笔记

时间:2022-10-16 23:47:39浏览次数:60  
标签:适应 int double 笔记 辛普森 dfrac 2n displaystyle

对于一个二次函数 \(f(x) = ax^2 + bx + c\),积分得 \(F(x) = \displaystyle\int_0^x f(t) \, \mathrm{d}t = \dfrac{a}{3}x^3 + \dfrac{b}{2}x^2 + cx + C\)。

于是

\[\displaystyle\int_l^r f(x) \, \mathrm{d}x = F(r) - F(l) \]

\[= \dfrac{a(r^3 - l^3)}{3} + \dfrac{b(r^2 - l^2)}{2} + c(r - l) + (C - C) \]

\[= (r - l)[\dfrac{a(r^2 + rl + l^2)}{3} + \dfrac{b(r + l)}{2} + c] \]

\[= \dfrac{r - l}{6}(2ar^2 + 2arl + 2al^2 + 3br + 3bl + 6c) \]

\[= \dfrac{r - l}{6}\{(ar^2 + br + c) + (al^2 + bl + c) + 4[a(\dfrac{l + r}{2})^2 + b(\dfrac{l + r}{2}) + c]\} \]

\[= \dfrac{(r - l)(f(l) + 4f(\dfrac{l + r}{2}) + f(r))}{6} \]

以上即为辛普森公式。

普通辛普森法

为了求 \(\displaystyle\int^r_l f(x) \, \mathrm{d}x\),可以将区间 \([l, r]\) 分为\(2n\)个等长的区间 \([g_i, g_{i + 1}](i \in \{1, 2, ..., 2n\})\)。设 \(h = \dfrac{r - l}{2n}\),近似地计算过 \((g_{i - 1}, f(g_{i - 1}))\)、\((g_i, f(g_i))\)、\((g_{i + 1}, f(g_{i + 1}))\) 三点的二次函数在区间 \([g_{i - 1}, g_{i + 1}]\) 的积分。当 \(n\) 足够大时,计算结果便越接近原函数的积分。设 \(P(x)\) 为过该三点的函数,则

\[\displaystyle\int^r_l f(x) \, \mathrm{d}x \approx \displaystyle\sum_{i = 1}^{n} \displaystyle\int^{g_{2i + 1}}_{g_{2i - 1}} P(x) \, \mathrm{d}x \]

\[= \dfrac{h}{3} (\displaystyle\sum^{n}_{i = 1} f(g_{2i - 1}) + 4f(g_{2i}) + f(g_{2i + 1})) \]

\[= \dfrac{h}{3}(f(g_1) + 4f(g_2) + 2f(g_3) + 4f(g_4) + ... + 2f(g_{2n - 1}) + 4f(g_{2n}) + f(g_{2n+1})) \]

Code:

int n = 1e7;

double calc(double l, double r) {
    double h = (r - l) / (2 * n), res = f(l) + f(r);
    
    for (int i = 2; i < 2 * n; ++i)
        res += f(l + i * h) * (i & 1? 2: 4);
    
    return res * h / 3;
}

自适应辛普森法

考虑到当分割出的二次函数在该区间内已经足够接近原函数时,可以直接使用该积分值;而当二次函数仍不够接近时还需再分割,于是可以考虑分别用辛普森公式计算区间 \([l, r]\)、\([l, \dfrac{l + r}{2}]\)、\([\dfrac{l + r}{2}, r]\) 的积分值,若大区间的积分值与小区间的积分值和的差足够小,则可以认为二次函数的图像在该区间内足够接近原函数的图像,并直接返回大区间的积分值。否则,递归计算两个小区间。一般还需设定一个次数,当已经递归超过该次数时才开始判断是否可以直接返回。

P4525 【模板】自适应辛普森法 1 AC Code:

#include <cstdio>
#define simpson(l, r) ((r - l) * (f(l) + f(r) + 4 * f((l + r) / 2)) / 6)
#define f(x) (double(c * (x) + d) / (a * (x) + b))
#define abs(x) ((x) >= 0? (x): -(x))

using namespace std;

double a, b, c, d, L, R;

double calc(double l, double r, int step, double sps) {
    double mid = (l + r) / 2;
    double fl = simpson(l, mid), fr = simpson(mid, r);
    
    if (abs(fl + fr - sps) <= 1e-6 && step < 0)
        return sps;
    else
        return calc(l, mid, step - 1, fl) + calc(mid, r, step - 1, fr);
}

int main() {
    scanf("%lf %lf %lf %lf %lf %lf", &a, &b, &c, &d, &L, &R);
    printf("%lf", calc(L, R, 12, simpson(L, R)));
    
    return 0;
}

标签:适应,int,double,笔记,辛普森,dfrac,2n,displaystyle
From: https://www.cnblogs.com/wf715/p/Simpson-Integral.html

相关文章

  • acm训练笔记
    2022.10.16模拟赛2019ChinaCollegiateProgrammingContestFinal(CCPC-Final2019)L题意:只能直行或者右转,问有多少种走遍一个矩阵的方法。解法:构造题,考虑任意一种......
  • Flask学习笔记(十三)-Flask_WTF实现表单
    一、Web表单Web表单是Web应用程序的基本功能。它是HTML页面中负责数据采集的部件。表单有三个部分组成:表单标签、表单域、表单按钮。表单允许用户输入数据,负责HTML页......
  • SpringCloud学习笔记(三)——Ribbon
    一、restTemplate的使用我们直接通过实例来说明和理解。首先新建一个子模块,用来测试restTemplate的使用  在测试的主类中添加如下代码,我们就能够获取百度界面的htm......
  • 系统分析师学习笔记(8)-图论与图示网络的最大流量
    要找出图示的最大流量:1.找出最大运量的路径,该路径的最小值为瓶颈值,抽取该值;2.在找出的路径减去抽取值,为0的路径取消;3.在剩余的路径中,找出最大的抽取值,重复步骤1&2;4.将各个步......
  • 20201302姬正坤Linux第四章学习笔记
    第四章并发编程一、并行计算导论1、顺序算法与并行算法在描述顺序算法中,常用一个begin-end代码块列出算法。该代码块中的所有步骤都是通过某个任务依次执行的。而并行......
  • Java核心技术阅读笔记(第五章)
    Chapter5继承作者:Denis版本:1.0编写时间:2022/10/16编写地点:中国山西省5.1类、超类和子类如果一个类继承自另一个类,那么这个类被称为子类,被继承的类被称为超类......
  • 第四单元读书笔记
    第四章并发编程介绍Pthread中的线程操作,包括线程管理函数,互斥量、连接、条件变量和屏障等线程同步工具。4.1并行计算导论4.1.1顺序算法与并序算法使用cobegin-c......
  • 数据库学习笔记04- redis
    5,Redis基础redis--KV数据库--内存--单线程+异步i/o(多路io复用)计算密集型应用:多进程+多进程IO密集型应用:单线程+异步IO(协程)2008年--redis--》REmote......
  • Kubernetes学习笔记(四十):KodeKloud Mock Exam - 2
    Question1(15')Takeabackupoftheetcdclusterandsaveitto/opt/etcd-backup.db.Question2(15')CreateaPodcalledredis-storagewithimage:redis:alp......
  • Redis学习笔记
    基础篇-02.初识Redis-认识NoSQL_哔哩哔哩_bilibili,参考黑马程序员出品的Redis教程,感谢黑马!基础篇一、Redis入门1.认识NoSQL1.1 什么是NoSQLNoSQL最常见的解释是"n......