定积分与应用
定积分的 Riemann/Darboux 形式化定义、Newton-Leibniz 公式与微积分基本定理、换元与分部、反常积分、面积/体积/弧长/功。本篇以 Spivak/Apostol/Rudin 风格的严格分析视角,系统阐述从穷竭法到 Riemann 严格化再到 Lebesgue 测度与 Henstock-Kurzweill 积分的演化,配套 40+ Python/SymPy/scipy 代码示例、6 个 Mermaid 图与 10 道 Spivak 风格习题。
第 1 章 学习目标与导论
本篇是 FANDEX 微积分模块的第五篇,系统阐述定积分这一微积分最深刻的应用概念。本篇以 Spivak《Calculus》4th Edition、Apostol《Calculus》Vol 1/2、Rudin《Principles of Mathematical Analysis》3rd Edition、Royden《Real Analysis》4th Edition 与 Folland《Real Analysis》2nd Edition 为标杆,采用严格分析风格,所有核心概念均配 ε-δ 或 Darboux 上下和的形式化定义,所有定理均附证明或证明思路。
1.1 学习目标
完成本篇学习后,学习者将能够:
- 记忆 Riemann 和、Darboux 上下和、上下积分与 mesh 的形式化定义,能够准确陈述 Riemann 可积的 ε-δ 判据(对应 Bloom:remember)
- 理解 Newton-Leibniz 公式的几何意义与严格证明路径,掌握变限积分求导与微积分第一/第二基本定理的相互关系(对应 Bloom:understand)
- 应用换元法、分部积分法、Wallis 公式、对称性化简等技巧计算典型定积分与反常积分(对应 Bloom:apply)
- 分析 Riemann、Darboux、Lebesgue、Henstock-Kurzweill 四种积分理论的等价性、包含关系与适用边界(对应 Bloom:analyze)
- 评估反常积分的绝对收敛与条件收敛,识别无穷区间积分、瑕积分、Fubini 定理使用中的常见陷阱(对应 Bloom:evaluate)
- 创造性地将定积分应用于几何度量(面积/体积/弧长)、物理建模(做功/质心/转动惯量)与工程计算(ML 损失、概率密度、Monte Carlo、Black-Scholes 定价)(对应 Bloom:create)
1.2 本篇的定位
定积分是微积分从”局部变化率”走向”整体累积量”的桥梁。如果说导数刻画”瞬时”,积分则刻画”总和”。Newton 与 Leibniz 在 17 世纪独立发现二者通过微积分基本定理互为逆运算,这是 17 世纪数学最辉煌的成就。然而,积分的严格化比微分更艰难:直到 1854 年 Riemann 才给出第一个一般性的严格定义,1902 年 Lebesgue 进一步将其推广到更广的函数类,1957-1961 年 Henstock 与 Kurzweil 又构造了更精细的积分理论。
本篇严格遵循后者的现代观点,放弃”积分是无穷小求和”这种朴素直觉,转而用”积分是 Riemann 和的极限,且此极限存在与否由 Darboux 上下和的收敛性判定”这一严格框架。我们同时引入 Lebesgue 测度与 Henstock-Kurzweill 积分的对比视角,使读者理解为何 20 世纪的概率论、泛函分析、偏微分方程都选择 Lebesgue 积分作为基础。
本篇假定读者已掌握 FANDEX 模块 calculus/函数与极限 与 calculus/导数与微分 的内容,熟悉 ε-δ 语言、连续性、导数定义与基本求导法则。
第 2 章 历史动机:积分理论的发展史
积分思想的演化贯穿了 2400 余年的数学史,从古希腊的穷竭法到 20 世纪的 Henstock-Kurzweill 积分,每一次严格化都引发了数学基础的革命。本章按时间线梳理这一过程。
timeline
title 积分理论发展史
公元前 4 世纪 : Eudoxus 穷竭法
公元前 3 世纪 : Archimedes 系统运用
1675-1684 : Leibniz 发明积分记号
1665-1666 : Newton 流数法
1823 : Cauchy 严格化定积分
1854 : Riemann 一般定义
1875 : Darboux 上下和简化
1902 : Lebesgue 测度论
1907 : Fubini 定理
1957-1961 : Henstock-Kurzweill 积分
2.1 古希腊:穷竭法的诞生(公元前 4 世纪)
穷竭法(method of exhaustion)是积分思想的最早雏形,由 Eudoxus of Cnidus(约公元前 408-355 年)提出,后被 Archimedes(公元前 287-212 年)系统运用。
Eudoxus 的核心思想:为了证明某个曲边图形的面积等于某个已知值,可以构造一系列内接(或外切)的多边形,使其面积逐步逼近目标值;若多边形面积与目标值之差可以”穷竭”(任意小),则目标值即为曲边图形的面积。
Archimedes 的应用:利用穷竭法,Archimedes 证明了:
- 圆的面积等于 ,即
- 球的体积公式
- 抛物线弓形面积等于同底等高三角形面积的
# 数值验证 Archimedes 的圆面积逼近
# 用正 n 边形内接圆逼近圆面积 S = π r²
import math
def polygon_area(n, r=1):
"""计算半径 r 的圆内接正 n 边形面积
参数:
n: 多边形边数
r: 圆半径
返回:
内接正 n 边形面积
"""
return 0.5 * n * r**2 * math.sin(2 * math.pi / n)
# 随着 n 增大,多边形面积逼近 π
for n in [6, 12, 24, 48, 96, 1000, 100000]:
area = polygon_area(n)
print(f"n={n:>6}: 面积 = {area:.10f}, 误差 = {math.pi - area:.2e}")
# 输出:
# n= 6: 面积 = 2.5980762114, 误差 = 5.44e-01
# n= 12: 面积 = 3.0000000000, 误差 = 1.42e-01
# n= 24: 面积 = 3.1058285412, 误差 = 3.58e-02
# n= 48: 面积 = 3.1326286133, 误差 = 8.96e-03
# n= 96: 面积 = 3.1393502030, 误差 = 2.24e-03
# n= 1000: 面积 = 3.1415719828, 误差 = 2.07e-05
# n=100000: 面积 = 3.1415926019, 误差 = 5.17e-08
穷竭法的本质已经包含了极限思想:“对于任意给定的(误差)ε > 0,存在 N,使得 n > N 时误差 < ε”。但古希腊人并未将这一过程抽象为独立的”极限”概念,而是将其作为反证法的工具——这正是”穷竭”之名的由来:用一系列多边形把曲边图形与目标值的差额”耗尽”。
2.2 17 世纪:Newton 与 Leibniz 的微积分发明
2.2.1 Newton 的流数法(1665-1666)
Isaac Newton(1643-1727)在 1665-1666 年间因瘟疫离开剑桥返回伍尔索普庄园期间,发展了他称之为”流数法”(method of fluxions)的微积分。Newton 将变量视为随时间流动的量(fluents),其变化率称为流数(fluxions)。
若 与 都是随时间变化的量,Newton 记 、 为它们的流数,即:
Newton 的核心创新是将运动作为几何的基础,这使得瞬时速度、切线斜率、面积等问题统一在同一个框架下。在《自然哲学的数学原理》(1687)中,Newton 利用流数法计算了行星运动、潮汐、彗星轨道等一系列物理问题。
2.2.2 Leibniz 的微分法与 ∫ 记号(1675-1684)
Gottfried Wilhelm Leibniz(1646-1716)独立发展了微积分,他引入了现代记号:
- 表示 的无穷小变化(differential)
- 表示求和(integral,源自拉丁语 “summa” 的拉长 S)
- 表示导数
Leibniz 在 1675 年 10 月 29 日的手稿中首次使用 ∫ 符号(此前用 omn. 表示 “omnia” 求和)。1684 年他发表《Nova Methodus pro Maximis et Minimis》正式公布微分法,1686 年发表积分法。Leibniz 的记号直觉、灵活,在 17-18 世纪迅速流传欧洲大陆,现代微积分的记号基本沿用 Leibniz 的体系。
Leibniz 的核心贡献之一是微积分基本定理的早期形式:
这两个公式将”求和”与”求导”这两个看似相反的运算统一为逆运算。
2.2.3 Newton 与 Leibniz 的核心困难
尽管 Newton 与 Leibniz 的方法极其有效,但他们的基础都建立在”无穷小量”(infinitesimal)这一模糊概念上。无穷小量既非零(可用于除法),又等于零(可被忽略),这在逻辑上是矛盾的。这一矛盾被爱尔兰哲学家 Berkeley 大主教在 1734 年《The Analyst》中尖锐批评:
“它们既不是有限量,也不是无穷小量,也不是无。难道我们不能称它们为已消逝量的幽灵吗?”
Berkeley 的批评直接推动了 19 世纪分析严格化的运动。
2.3 19 世纪:Cauchy 与 Riemann 的严格化
2.3.1 Cauchy 的积分定义(1823)
Augustin-Louis Cauchy(1789-1857)在 1823 年的《Résumé des leçons données à l’École royale polytechnique sur le calcul infinitésimal》中首次给出了定积分的严格定义:
设 在 上连续,取等距分割 ,作和 。当 时, 趋于一个极限,称为 在 上的积分,记为 。
Cauchy 的定义比 Newton-Leibniz 的”无穷小求和”严格,但仍局限于连续函数,且依赖于等距分割的特殊性。
2.3.2 Riemann 的一般定义(1854)
Bernhard Riemann(1826-1866)在 1854 年的就职论文《论三角级数表示函数的可能性》(Über die Darstellbarkeit einer Function durch eine trigonometrische Reihe)中,将 Cauchy 的定义推广到一般有界函数与任意分割:
设 在 上有界,取任意分割 ,任取介点 ,作 Riemann 和 。若当 时 趋于一个不依赖于分割与介点的极限,则称 在 上 Riemann 可积,该极限称为 的 Riemann 积分。
Riemann 的关键创新是:
- 允许任意分割(不限于等距);
- 允许任意介点(不限于端点);
- 不要求连续,仅要求有界。
Riemann 还构造了一个著名的反例:在任意靠近每一点的点都不连续的函数,仍然可以 Riemann 可积。这是通过将间断点集控制为”零测度”实现的——这一概念后来被 Lebesgue 严格化。
2.3.3 Darboux 的简化(1875)
Jean-Gaston Darboux(1842-1917)在 1875 年的论文《Mémoire sur la théorie des fonctions discontinues》中引入了上下和的方法,将 Riemann 的定义等价简化:
对分割 ,定义:
其中 ,。Darboux 证明了:
Darboux 的表述更便于证明与教学,现代分析教材多采用 Darboux 形式。
2.4 20 世纪:Lebesgue 测度与 Henstock-Kurzweill 积分
2.4.1 Lebesgue 积分(1902)
Henri Lebesgue(1875-1941)在 1902 年的博士论文《Intégrale, longueur, aire》中提出了一种全新的积分理论,核心思想是:
Riemann 积分对 轴分割,Lebesgue 积分对 轴分割。
形式地说,Lebesgue 将函数 的值域分解为小段 ,考察 的原像 ,用这些原像的”测度”(measure)代替长度,作和:
Lebesgue 积分的优势:
- 更广的可积函数类:Dirichlet 函数 在 上 Riemann 不可积,但 Lebesgue 可积(积分值为 0,因为有理数集测度为 0);
- 更好的极限交换条件:Lebesgue 控制收敛定理、单调收敛定理远比 Riemann 理论下的相应结果强大;
- 完备性:Lebesgue 可积函数空间 是完备的(Riemann 可积函数空间不完备)。
Lebesgue 积分成为 20 世纪概率论、泛函分析、偏微分方程、调和分析的基础。
2.4.2 Fubini 定理(1907)
Guido Fubini(1879-1943)在 1907 年证明了重积分与累次积分的关系定理:
若 在 上 Lebesgue 可积(即 ),则:
Fubini 定理是多元积分理论的核心,使重积分可化为累次积分计算。其条件”绝对可积”是关键——若仅条件收敛,累次积分可能存在但不相等(Tonelli 给出了非负函数情形的补充)。
2.4.3 Henstock-Kurzweill 积分(1957-1961)
Ralph Henstock(1923-2007)与 Jaroslav Kurzweil(1926-)在 1957-1961 年间独立提出了一种比 Lebesgue 更精细的积分理论:
对每个点 ,赋予一个正数 (“规范” gauge),取分割 使每个子区间 满足 。若 Riemann 和的极限存在,则称 Henstock-Kurzweill 可积。
Henstock-Kurzweill 积分(又称规范积分或完全积分)的关键特点:
- 比 Lebesgue 更广:每个 Lebesgue 可积函数都 Henstock-Kurzweill 可积,反之不然;
- 条件收敛可积: 在 HK 意义下可积(条件收敛),但 Lebesgue 不可积;
- Newton-Leibniz 公式最广形式:每个导函数都 HK 可积,且 ,这在 Riemann 与 Lebesgue 理论中均不成立。
Henstock-Kurzweill 积分在微分方程理论与非绝对收敛积分的研究中占有重要地位。
# 数值演示:Dirichlet 函数的 Riemann 不可积与 Lebesgue 可积
import numpy as np
# 真正的 Lebesgue 积分:在 [0,1] 上,有理数集测度为 0
# 故 ∫_0^1 1_Q dx = 1 · m(Q ∩ [0,1]) = 1 · 0 = 0
print("Lebesgue 积分 ∫_0^1 1_Q dx = 0 (因为有理数集测度为 0)")
print("Riemann 积分不存在(上下和之差恒为 1)")
# 概念验证:用大量随机采样近似 Lebesgue 测度
# 在 [0,1] 内独立均匀采样,落在有理数集的概率 = 0
np.random.seed(42)
N = 1000000
samples = np.random.rand(N)
# 浮点数都是有理数,故 f(samples) 全为 1,这是浮点限制
# 但概念上,Lebesgue 积分 = 0 · m(无理数集) + 1 · m(有理数集) = 0 + 0 = 0
print(f"概念上 Lebesgue 积分 = 0(有理数集测度 0 × 函数值 1 + 无理数集测度 1 × 函数值 0)")
第 3 章 形式化定义:Riemann 与 Darboux
本章给出 Riemann 积分与 Darboux 积分的形式化定义,并证明二者的等价性。所有定义与定理均遵循 Rudin《Principles of Mathematical Analysis》第 6 章的表述。
3.1 分割、mesh 与 Riemann 和
定义 3.1(分割):设 为闭区间。 的一个分割 是有限点集 ,满足:
子区间 的长度记为 。
定义 3.2(mesh / 模):分割 的模(mesh,或称细度)定义为:
mesh 越小,分割越细。
定义 3.3(refine / 加细):若 (即 在 的基础上增加新分点),则称 是 的加细(refinement)。
定义 3.4(Riemann 和):设 有界, 为分割,任取介点 ,称:
为 关于分割 与介点 的 Riemann 和。
3.2 Darboux 上下和与上下积分
定义 3.5(Darboux 上下和):设 有界, 为分割,记:
定义:
- 上和(upper sum):
- 下和(lower sum):
显然 ,即 Riemann 和被 Darboux 上下和夹逼。
# Darboux 上下和的数值计算
import numpy as np
def darboux_sums(f, a, b, n):
"""计算 f 在 [a,b] 上的 Darboux 上下和(等距分割 n 段)
参数:
f: 被积函数
a, b: 积分下上限
n: 分割段数
返回:
(下和, 上和)
"""
xs = np.linspace(a, b, n + 1)
lower = 0.0
upper = 0.0
for k in range(n):
# 在 [xs[k], xs[k+1]] 内取稠密采样估计上下确界
sub = np.linspace(xs[k], xs[k+1], 1000)
fvals = f(sub)
lower += fvals.min() * (xs[k+1] - xs[k])
upper += fvals.max() * (xs[k+1] - xs[k])
return lower, upper
# 示例:f(x) = x² 在 [0,1] 上,真值 1/3
f = lambda x: x**2
print(f"{'n':>6} {'L(f,P)':>14} {'U(f,P)':>14} {'U-L':>14}")
for n in [2, 4, 8, 16, 32, 64, 128]:
L, U = darboux_sums(f, 0, 1, n)
print(f"{n:>6} {L:>14.10f} {U:>14.10f} {U-L:>14.4e}")
# 输出(典型):
# n= 2 L=0.0781250000 U=0.5781250000 U-L=5.0000e-01
# n= 4 L=0.1914062500 U=0.4414062500 U-L=2.5000e-01
# n= 8 L=0.2441406250 U=0.3691406250 U-L=1.2500e-01
# n= 16 L=0.2685546875 U=0.3325195312 U-L=6.3965e-02
# n= 32 L=0.2805175781 U=0.3117675781 U-L=3.1250e-02
# n= 64 L=0.2863769531 U=0.2999877930 U-L=1.5611e-02
# n= 128 L=0.2892456055 U=0.2960052490 U-L=7.7596e-03
# 当 n→∞ 时 L,U → 1/3,且 U-L → 0
定义 3.6(上下积分): 在 上的上积分与下积分定义为:
其中 与 取遍所有分割 。
引理 3.1(下和不超过上和):对任意两个分割 ,有 。
证明:取 (公共加细),由加细使下和增、上和不增:
故 ,即 。
3.3 Riemann 可积性条件
定义 3.7(Riemann 可积): 在 上 Riemann 可积,若 ,此公共值记为 。
定理 3.1(Riemann 可积的 Darboux 判据):设 有界,则以下等价:
(i) Riemann 可积; (ii) 对任意 ,存在分割 使 ; (iii) 当 时 ; (iv) 对任意 ,存在 ,使对任意分割 满足 且任意介点 ,有 。
证明思路:
- (i) (ii):由上下积分的定义直接得到;
- (ii) (iii):由”加细不增上和不减下和”的引理,可构造一致收敛的分割序列;
- (iii) (iv):利用 的夹逼;
- (iv) (i):由 Riemann 和的极限存在即可。
flowchart LR
A[f 有界] --> B{Riemann 可积?}
B -->|判据1| C[inf U = sup L]
B -->|判据2| D[∀ε ∃P: U-L<ε]
B -->|判据3| E[||P||→0 时 U-L→0]
B -->|判据4| F[Riemann 和极限<br/>与介点无关]
C <--> D <--> E <--> F
D --> G[典型可积类]
G --> H[连续函数]
G --> I[单调有界函数]
G --> J[有限间断点]
G --> K[间断点集<br/>Lebesgue 测度 0]
3.4 Riemann 可积函数类
定理 3.2(连续函数可积):若 在 上连续,则 Riemann 可积。
证明:由 Cantor 定理, 在紧集 上一致连续。对任意 ,存在 使 。取分割 使 ,则每个子区间内 ,故:
由 Riemann 判据, 可积。
定理 3.3(单调函数可积):若 在 上单调有界,则 Riemann 可积。
证明:设 单调递增,取等距分割 使 ,则:
定理 3.4(有限间断点可积):若 在 上有界且仅有有限个间断点,则 Riemann 可积。
证明:将 分成包含间断点的小区间(总长度可任意小)与其余区间(连续故可积),分别控制两部分对 的贡献。
定理 3.5(Lebesgue 判据): 在 上 Riemann 可积当且仅当 有界且其间断点集的 Lebesgue 测度为零。
这是 Riemann 可积性的最深刻刻画,由 Lebesgue 在 1902 年证明。它说明 Riemann 可积函数”几乎处处连续”。
# Thomae 函数:可数个间断点但 Riemann 可积的反例
# f(x) = 1/q 若 x = p/q 为既约分数,f(0) = 1,f(无理数) = 0
import numpy as np
from fractions import Fraction
def thomae(x):
"""Thomae 函数(爆米花函数)
参数:
x: 输入值(浮点近似)
返回:
若 x 接近 p/q(既约)则返回 1/q,若接近无理数则返回 0
"""
f = Fraction(x).limit_denominator(1000)
p, q = f.numerator, f.denominator
return 1.0 / q if q > 0 else 0.0
# Thomae 函数在 (0,1) 上有理点不连续、无理点连续
# 间断点集(有理数集)测度为 0,故 Riemann 可积
# 积分值 = 0(因 f 仅在有理点非零,而有理点集测度 0)
xs = np.linspace(0.001, 0.999, 10000)
vals = [thomae(x) for x in xs]
print(f"Thomae 函数在 [0,1] 上的最大值: {max(vals):.6f}")
print(f"Thomae 函数在 [0,1] 上的均值: {np.mean(vals):.6e}")
print(f"Riemann 积分值 = 0(由 Lebesgue 判据,间断点集测度 0)")
3.5 Riemann 和的几何意义
graph TB
subgraph "Riemann 和的几何意义"
A["曲线 y = f(x)"] --> B["分割 [a,b] 为 n 段"]
B --> C["每段选介点 ξ_k"]
C --> D["作矩形 fξ_k × Δx_k"]
D --> E["Riemann 和 = 矩形面积之和"]
E --> F{"||P|| → 0"}
F -->|可积| G["极限 = 曲边梯形面积"]
F -->|不可积| H["极限不存在或<br/>依赖介点选择"]
end
style G fill:#cfc,stroke:#0a0
style H fill:#fcc,stroke:#a00
Riemann 和的几何本质是:用一系列矩形面积之和逼近曲边梯形的面积。当分割足够细时,这种逼近的误差可任意小——前提是函数 在每个子区间上的”振荡”(oscillation,即 )足够小。这正是 Lebesgue 判据”间断点集测度为零”的几何含义。
第 4 章 理论推导:核心定理的证明
本章给出微积分基本定理、Fubini 定理、变量替换定理、分部积分、第一/第二中值定理的严格证明或证明思路,所有证明遵循 Apostol 与 Rudin 的风格。
4.1 微积分基本定理
微积分基本定理(Fundamental Theorem of Calculus, FTC)是微积分最重要的定理,它揭示了微分与积分的互逆关系。分为第一形式(变限积分求导)与第二形式(Newton-Leibniz 公式)。
4.1.1 第一形式:变限积分求导
定理 4.1(FTC 第一形式):设 在 上 Riemann 可积,定义变限积分:
则 在 上 Lipschitz 连续。进一步,若 在 处连续,则 在 处可导且 。
证明(连续性部分):由 有界,设 ,则:
故 Lipschitz 连续。
证明(可导性部分):设 在 处连续,对任意 ,存在 使 。当 时:
故 。
推论:若 在 上连续,则 是 的一个原函数,即 。这保证连续函数的原函数存在。
# 数值验证 FTC 第一形式:变限积分求导
import numpy as np
from scipy.integrate import quad
# 取 f(x) = cos(x),其变限积分 Φ(x) = ∫_0^x cos(t) dt = sin(x)
# 应有 Φ'(x) = cos(x)
f = np.cos
Phi = lambda x: quad(f, 0, x)[0] # 变限积分
# 数值导数 vs 解析导数
xs = np.linspace(0.1, 3, 20)
h = 1e-6
num_deriv = [(Phi(x + h) - Phi(x - h)) / (2 * h) for x in xs]
ana_deriv = np.cos(xs)
for x, nd, ad in zip(xs[:5], num_deriv[:5], ana_deriv[:5]):
print(f"x={x:.3f}, Φ'(x) 数值={nd:.8f}, cos(x)={ad:.8f}, 误差={abs(nd-ad):.2e}")
# 输出(典型):
# x=0.100, Φ'(x) 数值=0.99500417, cos(x)=0.99500417, 误差=2.07e-10
# x=0.258, Φ'(x) 数值=0.96680497, cos(x)=0.96680497, 误差=2.07e-10
4.1.2 第二形式:Newton-Leibniz 公式
定理 4.2(FTC 第二形式 / Newton-Leibniz 公式):设 在 上 Riemann 可积,且存在 使 在 上处处成立(或除有限个点外成立),则:
证明:取分割 ,由中值定理,存在 使:
求和:
令 ,右边趋于 ,左边为定值 ,故二者相等。
# Newton-Leibniz 公式数值验证
import sympy as sp
x = sp.Symbol('x')
f_expr = x**3 + sp.sin(x)
F_expr = sp.integrate(f_expr, x) # 原函数
print(f"f(x) = {f_expr}")
print(f"F(x) = ∫f dx = {F_expr}")
# 计算 ∫_0^π f(x) dx = F(π) - F(0)
a_val, b_val = 0, sp.pi
integral_analytic = sp.integrate(f_expr, (x, a_val, b_val))
F_b = F_expr.subs(x, b_val)
F_a = F_expr.subs(x, a_val)
newton_leibniz = F_b - F_a
print(f"\n∫_0^π f(x) dx (直接定积分) = {integral_analytic} ≈ {float(integral_analytic):.10f}")
print(f"F(π) - F(0) = {sp.simplify(newton_leibniz)} ≈ {float(newton_leibniz):.10f}")
print(f"两者一致: {sp.simplify(integral_analytic - newton_leibniz) == 0}")
# 输出(典型):
# f(x) = x**3 + sin(x)
# F(x) = ∫f dx = x**4/4 - cos(x)
# ∫_0^π f(x) dx = π**4/4 + 1 + 1 ≈ 25.3890...
# F(π) - F(0) = π**4/4 + 2 ≈ 25.3890...
graph LR
subgraph "Newton-Leibniz 的几何本质"
A["微分: 局部变化率<br/>F'(x) = f(x)"] --> C["FTC 桥梁"]
B["积分: 整体累积<br/>∫_a^b f dx"] --> C
C --> D["F(b) - F(a) = ∫_a^b F' dx<br/>= ∫_a^b f dx"]
end
style C fill:#fcf,stroke:#a0a
4.2 积分中值定理
4.2.1 第一中值定理
定理 4.3(积分第一中值定理):设 在 上连续, 在 上 Riemann 可积且不变号(即 或 ),则存在 使:
证明:设 ,记 ,( 连续故取到最值)。则 ,积分得:
若 则结论平凡;否则 ,由介值定理存在 使 。
4.2.2 第二中值定理
定理 4.4(积分第二中值定理):设 在 上 Riemann 可积, 在 上单调,则存在 使:
证明思路:用 Abel 求和分部法(对 的单调性敏感),将积分转化为 的形式,再应用第一中值定理。
第二中值定理在反常积分的 Dirichlet 判别法中起关键作用。
# 第二中值定理数值验证
import numpy as np
from scipy.integrate import quad
from scipy.optimize import brentq
# f(x) = sin(x), g(x) = x 单调递增, [a,b] = [0, π]
# 应存在 c ∈ [0,π] 使 ∫_0^π sin(x)·x dx = 0·∫_0^c sin + π·∫_c^π sin
f = np.sin
g = lambda x: x
a, b = 0, np.pi
lhs, _ = quad(lambda x: f(x)*g(x), a, b)
print(f"LHS = ∫_0^π sin(x)·x dx = {lhs:.10f}") # 应为 π
# 求解 c:g(a)·∫_a^c f + g(b)·∫_c^b f = 0·∫_0^c sin + π·∫_c^π sin
# = π · (-cos(π) + cos(c)) = π(1 + cos(c))
# 令 π(1 + cos(c)) = π → cos(c) = 0 → c = π/2
def equation(c):
int_ac, _ = quad(f, a, c)
int_cb, _ = quad(f, c, b)
return g(a)*int_ac + g(b)*int_cb - lhs
c_sol = brentq(equation, a, b)
print(f"c = {c_sol:.10f} (理论值 π/2 = {np.pi/2:.10f})")
print(f"误差: {abs(c_sol - np.pi/2):.2e}")
# 输出(典型):
# LHS = ∫_0^π sin(x)·x dx = 3.1415926536
# c = 1.5707963268 (理论值 π/2 = 1.5707963268)
# 误差: 0.00e+00
4.3 分部积分
定理 4.5(分部积分):设 可导且 在 上 Riemann 可积,则:
证明:由乘积求导法则 ,两边积分:
移项即得。
分部积分是计算含有乘积的积分的核心技巧,其本质是乘积求导法则的逆运用。
# 分部积分典型例题:∫_0^π x·sin(x) dx
import sympy as sp
x = sp.Symbol('x')
# 方法1:直接用 sympy 积分
result1 = sp.integrate(x * sp.sin(x), (x, 0, sp.pi))
print(f"∫_0^π x·sin(x) dx = {result1}") # 输出: π
# 方法2:分部积分手动推导
# u = x, dv = sin(x) dx → du = dx, v = -cos(x)
# ∫ x·sin(x) dx = -x·cos(x) + ∫ cos(x) dx = -x·cos(x) + sin(x) + C
u, v = x, -sp.cos(x)
F = u*v - sp.integrate(sp.diff(u, x) * v, x)
print(f"分部积分得原函数: {F}")
print(f"F(π) - F(0) = {F.subs(x, sp.pi) - F.subs(x, 0)}") # 输出: π
4.4 变量替换定理
定理 4.6(变量替换):设 连续, 满足:
- 在 上 (连续可导);
- ;
- 单调(或 在 上),
则:
证明思路:设 为 的原函数(由 FTC 第一形式,),则 是 的原函数:
由 Newton-Leibniz:
注:变量替换定理的多元形式涉及 Jacobian 行列式(见第 4.5 节)。
# 变量替换典型例题:∫_0^4 dx/(1+√x)
# 令 t = √x, x = t², dx = 2t dt, x=0→t=0, x=4→t=2
# ∫_0^2 (2t)/(1+t) dt = 2∫_0^2 (1 - 1/(1+t)) dt = 2[t - ln(1+t)]_0^2 = 2(2 - ln3)
import sympy as sp
t = sp.Symbol('t')
x = sp.Symbol('x')
# 原积分
I1 = sp.integrate(1/(1 + sp.sqrt(x)), (x, 0, 4))
print(f"直接积分 ∫_0^4 dx/(1+√x) = {I1} = {float(I1):.10f}")
# 变量替换后
integrand_sub = 2*t / (1 + t)
I2 = sp.integrate(integrand_sub, (t, 0, 2))
print(f"换元后 ∫_0^2 2t/(1+t) dt = {I2} = {float(I2):.10f}")
print(f"两者一致: {sp.simplify(I1 - I2) == 0}")
# 输出:
# 直接积分 ∫_0^4 dx/(1+√x) = -2*log(3) + 4 = 1.8027754178
# 换元后 ∫_0^2 2t/(1+t) dt = -2*log(3) + 4 = 1.8027754178
# 两者一致: True
4.5 多元情形:Jacobian 与变量替换
多元积分的变量替换涉及 Jacobian 行列式:
定理 4.7(多元变量替换):设 是 微分同胚, 连续,则:
其中 是 Jacobian 行列式的绝对值,表示体积局部伸缩比。
经典应用:
- 极坐标:,
- 柱坐标:,
- 球坐标:,
# Jacobian 计算示例:球坐标变换
import sympy as sp
rho, phi, theta = sp.symbols('rho phi theta', positive=True)
# 球坐标:x = ρ sinφ cosθ, y = ρ sinφ sinθ, z = ρ cosφ
x = rho * sp.sin(phi) * sp.cos(theta)
y = rho * sp.sin(phi) * sp.sin(theta)
z = rho * sp.cos(phi)
J = sp.Matrix([
[sp.diff(x, rho), sp.diff(x, phi), sp.diff(x, theta)],
[sp.diff(y, rho), sp.diff(y, phi), sp.diff(y, theta)],
[sp.diff(z, rho), sp.diff(z, phi), sp.diff(z, theta)],
]).det()
J_simplified = sp.simplify(sp.trigsimp(J))
print(f"球坐标 Jacobian = {J_simplified}") # 应为 ρ²·sin(φ)
# 用球坐标计算球体积:V = ∫∫∫ ρ² sinφ dρ dφ dθ
V = sp.integrate(
rho**2 * sp.sin(phi),
(rho, 0, 1), (phi, 0, sp.pi), (theta, 0, 2*sp.pi)
)
print(f"单位球体积 = {V} = {float(V):.10f} (理论值 4π/3 = {float(4*sp.pi/3):.10f})")
# 输出:
# 球坐标 Jacobian = rho**2*sin(phi)
# 单位球体积 = 4*pi/3 = 4.1887902048
flowchart LR
A["原始区域 Ω'"] --> B["变量替换 T: Ω → Ω'"]
B --> C["计算 Jacobian J = |det ∂T/∂u|"]
C --> D["新被积函数 f(Tu)·|J|"]
D --> E["在 Ω 上积分"]
E --> F["结果与原积分一致"]
style B fill:#ccf,stroke:#006
style C fill:#fcf,stroke:#a0a
4.6 Fubini 定理
定理 4.8(Fubini 定理):设 可测,且 (绝对可积),则:
且两个累次积分相等。
Tonelli 定理(对非负函数的补充):若 可测,则上述等式成立(两边可能同为 )。
Fubini 定理的几何意义:三维体积可沿任意方向切片后积分。其条件”绝对可积”是关键——若仅条件收敛,累次积分可能存在但不相等。
经典反例(Fubini 失效):考虑 在 上,可验证:
两个累次积分不相等!原因是 在原点附近非绝对可积。
# Fubini 定理数值验证:∫∫_{[0,1]²} x·y dx dy
import numpy as np
from scipy.integrate import dblquad, quad
# 真值:∫_0^1 ∫_0^1 x·y dx dy = (∫_0^1 x dx)(∫_0^1 y dy) = (1/2)(1/2) = 1/4
true_val = 0.25
# 方法1:scipy.dblquad
I1, _ = dblquad(lambda y, x: x*y, 0, 1, 0, 1)
print(f"dblquad 计算: {I1:.10f}, 误差: {abs(I1 - true_val):.2e}")
# 方法2:累次积分
inner = lambda x: quad(lambda y: x*y, 0, 1)[0] # 内层 = x/2
I2, _ = quad(inner, 0, 1)
print(f"累次积分: {I2:.10f}, 误差: {abs(I2 - true_val):.2e}")
# 方法3:Monte Carlo
np.random.seed(0)
N = 100000
xs = np.random.rand(N)
ys = np.random.rand(N)
I3 = np.mean(xs * ys) # 区域体积=1
print(f"Monte Carlo: {I3:.10f}, 误差: {abs(I3 - true_val):.2e}")
# Fubini 反例验证:f(x,y) = (x²-y²)/(x²+y²)²
def f_bad(y, x):
if x == 0 or y == 0:
return 0.0
return (x**2 - y**2) / (x**2 + y**2)**2
# 注意:此积分在 [0,1]² 上不绝对可积,Fubini 失效
I_xy, _ = dblquad(f_bad, 0, 1, 0, 1, epsabs=1e-8)
print(f"\n反例 ∫∫ (x²-y²)/(x²+y²)² dx dy = {I_xy:.6f} (期望 ≈ π/4 ≈ {np.pi/4:.6f})")
# 累次积分顺序1:∫_0^1 [∫_0^1 f dy] dx
I1_order, _ = quad(lambda x: quad(lambda y: f_bad(y, x), 0, 1)[0], 0, 1)
print(f" ∫_0^1 ∫_0^1 f dy dx = {I1_order:.6f}")
# 累次积分顺序2:∫_0^1 [∫_0^1 f dx] dy
I2_order, _ = quad(lambda y: quad(lambda x: f_bad(y, x), 0, 1)[0], 0, 1)
print(f" ∫_0^1 ∫_0^1 f dx dy = {I2_order:.6f}")
print("两累次积分不相等 → Fubini 条件失效!")
graph TB
A[二重积分 ∬ f dA] --> B{f 是否绝对可积?}
B -->|是| C[Fubini 定理适用<br/>可化为累次积分]
B -->|否| D[Fubini 定理失效<br/>累次积分可能不等]
C --> E[∬ f dA = ∫ dx ∫ f dy<br/>= ∫ dy ∫ f dx]
D --> F[反例: x²-y²/(x²+y²)²<br/>两顺序结果符号相反]
style C fill:#cfc,stroke:#0a0
style D fill:#fcc,stroke:#a00
4.7 可积函数类的进一步刻画
定理 3.5(重述 Lebesgue 判据): 在 上 Riemann 可积 有界且其间断点集 的 Lebesgue 测度为零。
测度为零的集(零测集): 测度为零,若对任意 ,存在可数个区间 覆盖 使 。
零测集的例子:
- 有限集
- 可数集( 测度为零)
- Cantor 集(不可数但测度为零)
定理 4.9(有界变差函数可积):若 在 上为有界变差(BV),则 Riemann 可积。
证明:有界变差函数可分解为两单调函数之差(Jordan 分解),由定理 3.3 即得。
# 有界变差函数示例:f(x) = x·sin(1/x) 在 [0,1] 上是否有界变差?
import numpy as np
def f_bv(x):
"""f(x) = x·sin(1/x), f(0) = 0"""
x = np.where(x == 0, 1e-15, x)
return x * np.sin(1/x)
# 计算总变差:TV = Σ |f(x_k) - f(x_{k-1})|
xs = np.linspace(0, 1, 100001)
ys = f_bv(xs)
tv = np.sum(np.abs(np.diff(ys)))
print(f"f(x) = x·sin(1/x) 在 [0,1] 上的数值总变差: {tv:.4f}")
print("理论上该函数为有界变差(因 x→0 时 x 控制 sin(1/x) 的振荡幅度)")
print("故 Riemann 可积")
# 对比:g(x) = sin(1/x) 不是有界变差
def g_nobv(x):
x = np.where(x == 0, 1e-15, x)
return np.sin(1/x)
ys2 = g_nobv(xs)
tv2 = np.sum(np.abs(np.diff(ys2)))
print(f"\ng(x) = sin(1/x) 在 [0,1] 上的数值总变差: {tv2:.4f} (发散)")
print("但 g 在 (0,1] 连续、在 0 处无定义,若延拓则不可积")
第 5 章 定积分的计算技巧
本章总结定积分的核心计算技巧,所有方法均以严格推导为基础。
5.1 换元法
核心公式(重述定理 4.6):
关键提醒:换元时必须同步换上下限(从 换为 )。
# 换元法综合示例
import sympy as sp
x, t = sp.symbols('x t', positive=True)
# 例1:∫_0^1 √(1-x²) dx,令 x = sin t
I1 = sp.integrate(sp.sqrt(1 - x**2), (x, 0, 1))
print(f"∫_0^1 √(1-x²) dx = {I1} = {float(I1):.6f} (理论值 π/4 = {float(sp.pi/4):.6f})")
# 例2:∫_0^{ln2} e^x/(1+e^{2x}) dx,令 e^x = tan t
I2 = sp.integrate(sp.exp(x)/(1 + sp.exp(2*x)), (x, 0, sp.log(2)))
print(f"∫_0^ln2 e^x/(1+e^2x) dx = {I2} = {float(I2):.6f} (理论值 arctan(2) = {float(sp.atan(2)):.6f})")
# 例3:∫_0^1 x^4/(1+x²) dx,通过 x^4 = (x^4-1)+1 分解
I3 = sp.integrate(x**4/(1 + x**2), (x, 0, 1))
print(f"∫_0^1 x^4/(1+x²) dx = {I3} = {float(I3):.6f}")
5.2 分部积分
核心公式(重述定理 4.5):
典型应用模式:
- :
- 或 :
- :
- :
# 分部积分推导递推:Wallis 积分 I_n = ∫_0^{π/2} sin^n x dx
import sympy as sp
x = sp.Symbol('x')
n = sp.Symbol('n', positive=True, integer=True)
# 手动推导递推:I_n = (n-1)/n · I_{n-2}
# 取 u = sin^{n-1} x, dv = sin x dx
# → du = (n-1) sin^{n-2} x cos x dx, v = -cos x
# I_n = [-cos x · sin^{n-1} x]_0^{π/2} + (n-1)∫_0^{π/2} sin^{n-2} x cos²x dx
# = 0 + (n-1)∫ sin^{n-2} x (1 - sin²x) dx
# = (n-1)(I_{n-2} - I_n)
# 故 n·I_n = (n-1)·I_{n-2},即 I_n = (n-1)/n · I_{n-2}
# 数值验证 Wallis 公式
def wallis(n):
if n % 2 == 0: # 偶数
result = 1
for k in range(2, n+1, 2):
result *= (k-1) / k
return result * sp.pi / 2
else: # 奇数
result = 1
for k in range(3, n+1, 2):
result *= (k-1) / k
return result
for n_val in [1, 2, 3, 4, 5, 6, 10]:
exact = sp.integrate(sp.sin(x)**n_val, (x, 0, sp.pi/2))
wallis_val = wallis(n_val)
print(f"I_{n_val} = ∫_0^π/2 sin^{n_val}x dx = {exact} ≈ {float(exact):.6f}, Wallis={float(wallis_val):.6f}")
# 输出(典型):
# I_1 = 1 ≈ 1.000000
# I_2 = pi/2 ≈ 1.570796
# I_3 = 2/3 ≈ 0.666667
# I_4 = 3*pi/16 ≈ 0.589049
5.3 对称性化简
奇偶函数:
周期函数:若 以 为周期,则对任意 :
# 对称性化简示例
import sympy as sp
x = sp.Symbol('x')
# 例1:∫_{-1}^1 x³·cos²x dx (奇函数×偶函数=奇)
I1 = sp.integrate(x**3 * sp.cos(x)**2, (x, -1, 1))
print(f"∫_{-1}^1 x³·cos²x dx = {I1} (奇函数,积分=0)")
# 例2:∫_{-π/2}^{π/2} sin⁴x dx (偶函数)
I2 = sp.integrate(sp.sin(x)**4, (x, -sp.pi/2, sp.pi/2))
print(f"∫_{{-π/2}}^{{π/2}} sin⁴x dx = {I2} = {float(I2):.6f}")
# 例3:周期函数 ∫_0^{2π} sin(x)·cos(x) dx = 0
I3 = sp.integrate(sp.sin(x)*sp.cos(x), (x, 0, 2*sp.pi))
print(f"∫_0^2π sin·cos dx = {I3} (周期 2π,完整周期)")
5.4 Wallis 公式与渐近分析
Wallis 公式:
由此可推导 Stirling 公式的初等形式:
# Wallis 公式 → Stirling 公式数值验证
import math
def stirling(n):
"""Stirling 近似:n! ≈ √(2πn) (n/e)^n"""
return math.sqrt(2*math.pi*n) * (n/math.e)**n
print(f"{'n':>6} {'n!':>20} {'Stirling':>20} {'ratio':>12}")
for n in [1, 5, 10, 20, 50, 100]:
exact = math.factorial(n)
approx = stirling(n)
print(f"{n:>6} {exact:>20} {approx:>20.4f} {exact/approx:>12.8f}")
# 输出显示:ratio → 1,验证 Stirling 公式
第 6 章 反常积分
反常积分(improper integral)是将定积分推广到无穷区间或无界函数的工具,是 Riemann 积分的极限扩张。
6.1 无穷区间上的反常积分
定义 6.1:设 在 上有定义且在任意 上 Riemann 可积,若极限:
存在(有限),则称反常积分收敛;否则发散。类似定义 与 。
p-积分:
# p-积分收敛性数值实验
import numpy as np
from scipy.integrate import quad
print(f"{'p':>6} {'∫_1^∞ 1/x^p dx':>20} {'收敛?':>10}")
for p in [0.5, 1.0, 1.5, 2.0, 3.0]:
# 用大数近似 +∞,并观察收敛性
val_large, _ = quad(lambda x: 1/x**p, 1, 1e6)
val_inf, _ = quad(lambda x: 1/x**p, 1, np.inf)
converged = "收敛" if np.isfinite(val_inf) else "发散"
print(f"{p:>6.1f} {val_inf:>20.6f} {converged:>10}")
# 输出:
# p=0.5 → 发散(无穷)
# p=1.0 → 发散(无穷)
# p=1.5 → 收敛(2.0)
# p=2.0 → 收敛(1.0)
# p=3.0 → 收敛(0.5)
6.2 无界函数的反常积分(瑕积分)
定义 6.2:设 在 上有定义,(即 为瑕点),若极限:
存在,则称瑕积分收敛。
瑕积分的 p-判别:
# 瑕积分数值计算:∫_0^1 1/√x dx = 2
import numpy as np
from scipy.integrate import quad
# 直接用 quad 处理瑕点(需指定 points)
val, err = quad(lambda x: 1/np.sqrt(x), 0, 1, points=[0])
print(f"∫_0^1 1/√x dx = {val:.10f} (理论值 2.0)")
# 数值验证:对不同的 ε 看 ∫_ε^1 1/√x dx 的极限
for eps in [1e-1, 1e-2, 1e-4, 1e-8, 1e-15]:
v, _ = quad(lambda x: 1/np.sqrt(x), eps, 1)
print(f"ε={eps:.0e}: ∫_{eps}^1 1/√x dx = {v:.10f}, 偏离 2 的误差 = {abs(v-2):.2e}")
6.3 收敛判别法
比较判别法:设 在 上非负连续:
- 若 且 收敛 收敛
- 若 且 发散 发散
极限比较法:若 :
- : 与 同敛散
- : 收敛 收敛
- : 发散 发散
Dirichlet 判别法:若 单调趋于 0, 的原函数有界,则 收敛。
Abel 判别法:若 单调有界, 收敛,则 收敛。
# Dirichlet 判别法应用:∫_1^∞ sin(x)/x dx 条件收敛
import numpy as np
from scipy.integrate import quad
# 直接计算(数值上 ∞ 用大数近似)
val, _ = quad(lambda x: np.sin(x)/x, 1, np.inf, limit=200)
print(f"∫_1^∞ sin(x)/x dx = {val:.10f} (理论值 π/2 - Si(1) ≈ 0.62471326)")
# 验证非绝对收敛:∫_1^∞ |sin(x)|/x dx 发散
val_abs_partial, _ = quad(lambda x: np.abs(np.sin(x))/x, 1, 1000)
print(f"∫_1^1000 |sin(x)|/x dx = {val_abs_partial:.4f} (持续增长 → 发散)")
val_abs_large, _ = quad(lambda x: np.abs(np.sin(x))/x, 1, 10000)
print(f"∫_1^10000 |sin(x)|/x dx = {val_abs_large:.4f} (继续增长)")
6.4 绝对收敛与条件收敛
定义 6.3:
- 绝对收敛: 收敛 收敛
- 条件收敛: 收敛但 发散
关键事实:
- 绝对收敛是充分条件,保证积分值与”求和方式”无关;
- 条件收敛的积分对”截断方式”敏感,改变截断可能得到不同值。
经典条件收敛例子:
- (条件收敛)
- (Fresnel 积分,条件收敛)
# Fresnel 积分:∫_0^∞ sin(x²) dx = √(π/8)
import numpy as np
from scipy.integrate import quad
from scipy.special import fresnel
# 数值计算
val, _ = quad(lambda x: np.sin(x**2), 0, np.inf, limit=500)
theoretical = np.sqrt(np.pi/8)
print(f"∫_0^∞ sin(x²) dx = {val:.10f}")
print(f"理论值 √(π/8) = {theoretical:.10f}")
print(f"误差: {abs(val - theoretical):.2e}")
# 验证条件收敛:∫_0^∞ |sin(x²)| dx 发散
for upper in [10, 100, 1000, 10000]:
v, _ = quad(lambda x: np.abs(np.sin(x**2)), 0, upper, limit=200)
print(f"∫_0^{upper} |sin(x²)| dx = {v:.4f}")
# 输出:积分持续增长 → 发散
6.5 Gamma 函数与 Beta 函数
Gamma 函数:
性质:
- (分部积分)
- (正整数)
- (用极坐标变换)
- (余元公式)
Beta 函数:
关系:
# Gamma 函数与 Beta 函数
import math
from scipy.special import gamma, beta
from scipy.integrate import quad
import numpy as np
# Gamma 函数验证
print("Gamma 函数:")
for s in [0.5, 1, 1.5, 2, 3, 4, 5]:
val_numerical, _ = quad(lambda x: x**(s-1) * np.exp(-x), 0, np.inf)
val_scipy = gamma(s)
print(f" Γ({s}) = {val_numerical:.8f} (scipy: {val_scipy:.8f})")
print(f"\nΓ(1/2) = √π = {math.sqrt(math.pi):.8f}")
print(f"Γ(5) = 4! = {gamma(5)} = {math.factorial(4)}")
# Beta 函数与 Gamma 关系
print("\nBeta 函数:")
for p, q in [(1, 1), (2, 2), (0.5, 0.5), (3, 2)]:
B_num, _ = quad(lambda x: x**(p-1) * (1-x)**(q-1), 0, 1)
B_formula = gamma(p)*gamma(q) / gamma(p+q)
print(f" B({p},{q}) = {B_num:.8f} (公式: {B_formula:.8f})")
# 用 Gamma(1/2) 推导正态分布归一化
print(f"\n正态分布归一化:∫_{{-∞}}^∞ e^{{-x²/2}} dx = √(2π) = {math.sqrt(2*math.pi):.8f}")
# 因为 ∫_0^∞ e^{-t} t^{-1/2} dt = Γ(1/2) = √π, 令 t = x²/2 推导
第 7 章 对比分析:Riemann / Darboux / Lebesgue / Henstock-Kurzweill
本章系统对比四种积分理论,揭示它们的等价性、包含关系与适用边界。
7.1 四种积分的定义对照
| 积分理论 | 分割方式 | 介点选取 | 适用函数类 | 优势 |
|---|---|---|---|---|
| Riemann | 轴任意分割 | 任意介点 | 有界 + 间断点测度 0 | 几何直观 |
| Darboux | 轴任意分割 | 上下确界 | 同 Riemann(等价) | 易于证明 |
| Lebesgue | 轴分割(测度论) | 不需要介点 | 可测函数 | 极限交换强 |
| Henstock-Kurzweill | 轴 + 规范 | 任意介点 | 比 Lebesgue 更广 | N-L 公式最广 |
7.2 包含关系
具体地:
- 每个 Riemann 可积函数都 Lebesgue 可积,且积分值相同;
- 每个 Lebesgue 可积函数都 Henstock-Kurzweill 可积;
- 反向不成立:存在 Lebesgue 不可积但 HK 可积的函数(如 在 )。
# 数值比较:Dirichlet 函数在不同积分理论下的可积性
import numpy as np
from scipy.integrate import quad
# Dirichlet 函数:1_Q(x)
# 在 [0,1] 上:
# - Riemann: 不可积(上下和之差 = 1)
# - Lebesgue: 可积,∫ = 0 (因 m(Q∩[0,1]) = 0)
# - HK: 可积,∫ = 0 (HK 推广 Riemann,且与 Lebesgue 在有界情形一致)
# 用浮点近似验证 Riemann 不可积(每个子区间都有有理与无理,上下确界差 1)
def dirichlet_upper_sum(a, b, n):
"""Dirichlet 函数上和:每段上确界 = 1"""
return (b - a) # = Σ 1 · Δx_k = b - a
def dirichlet_lower_sum(a, b, n):
"""Dirichlet 函数下和:每段下确界 = 0"""
return 0.0
for n in [10, 100, 1000, 10000]:
U = dirichlet_upper_sum(0, 1, n)
L = dirichlet_lower_sum(0, 1, n)
print(f"n={n:>5}: U - L = {U - L:.4f} (恒为 1,不趋于 0 → Riemann 不可积)")
print(f"\nLebesgue 积分:∫_0^1 1_Q dx = 1 · m(Q∩[0,1]) = 1 · 0 = 0")
print(f"Henstock-Kurzweill 积分:与 Lebesgue 一致,= 0")
7.3 关键差异点
7.3.1 极限交换
Lebesgue 优势:
- 单调收敛定理(MCT):若 且 可测,则
- 控制收敛定理(DCT):若 a.e. 且 (可积),则
Riemann 劣势:即使 处处收敛到 且每个 Riemann 可积, 也可能不 Riemann 可积;即使可积, 也可能不趋于 。
经典反例:设 为 的指示函数(在 上)。每个 是阶梯函数 Riemann 可积,,但 在某些点(如 )无穷次取 0 与 1,极限函数不 Riemann 可积。
7.3.2 完备性
Lebesgue 优势:可积函数空间 在 范数 下完备(Banach 空间)。
Riemann 劣势:Riemann 可积函数在 范数下不完备——存在 Riemann 可积函数序列 使 ,但极限函数 不 Riemann 可积(只能 Lebesgue 可积)。
7.3.3 Newton-Leibniz 公式
HK 优势:每个导函数都 HK 可积,且 。
Riemann/Lebesgue 劣势:存在导函数 不 Riemann/Lebesgue 可积(Volterra 函数:处处可导但导数无界,故不 Riemann 可积;导数 Lebesgue 可积但 N-L 公式可能失效)。
# HK 积分示例:∫_0^1 F'(x) dx = F(1) - F(0) 即使 F' 不 Riemann 可积
# Volterra 型函数构造较复杂,这里用简化版:F(x) = x² sin(1/x²),F(0)=0
import numpy as np
from scipy.integrate import quad
import sympy as sp
x = sp.Symbol('x')
F_expr = sp.Piecewise((x**2 * sp.sin(1/x**2), x != 0), (0, True))
F_prime = sp.diff(F_expr, x)
print(f"F(x) = x² sin(1/x²)")
print(f"F'(x) = {F_prime}")
# F'(x) 在 0 附近无界(因 1/x² 项),不 Riemann 可积
# 但 HK 积分存在,且 ∫_0^1 F' dx = F(1) - F(0) = sin(1)
F_1 = float(F_expr.subs(x, 1))
F_0 = 0
print(f"\nF(1) - F(0) = {F_1 - F_0:.10f} = sin(1) = {np.sin(1):.10f}")
# 数值验证(用 quad 处理瑕点)
F_prime_func = sp.lambdify(x, F_prime, 'numpy')
val, err = quad(F_prime_func, 1e-10, 1, points=[0.01, 0.1, 0.5])
print(f"数值积分 ∫_0^1 F'(x) dx ≈ {val:.10f} (HK 与 Lebesgue 一致)")
7.4 工程取舍
| 应用场景 | 推荐理论 | 理由 |
|---|---|---|
| 大学微积分教学 | Riemann/Darboux | 直观、易理解 |
| 概率论 | Lebesgue | 期望/方差是 Lebesgue 积分 |
| 调和分析 | Lebesgue | 空间完备 |
| 偏微分方程 | Lebesgue + Sobolev | 弱解理论需要 |
| 微分方程理论 | Henstock-Kurzweill | N-L 公式最广 |
| 数值积分 | 不依赖理论 | 算法实现层 |
第 8 章 常见陷阱
本章总结定积分学习与使用中的常见陷阱,所有陷阱均配反例与正确处理方法。
8.1 陷阱 1:无穷区间积分的”对称化”
错误:写 (Cauchy 主值)。
正确:无穷区间积分定义为:
两个积分必须分别收敛。Cauchy 主值可能存在但积分发散。
反例:,(主值),但 发散,故 发散。
# 陷阱 1 反例:∫_{-∞}^∞ x dx
import numpy as np
from scipy.integrate import quad
# Cauchy 主值
for A in [10, 100, 1000, 10000]:
pv = quad(lambda x: x, -A, A)[0]
print(f"A={A}: ∫_{-A}^{A} x dx = {pv}") # 恒为 0
# 但分别积分
print("\n分别积分:")
val_pos, _ = quad(lambda x: x, 0, np.inf)
val_neg, _ = quad(lambda x: x, -np.inf, 0)
print(f"∫_0^∞ x dx = {val_pos}")
print(f"∫_{-∞}^0 x dx = {val_neg}")
print("两者均发散 → ∫_{-∞}^∞ x dx 发散,虽然 Cauchy 主值 = 0")
8.2 陷阱 2:瑕积分忽略瑕点
错误:直接套用 Newton-Leibniz 公式计算 。
正确: 是瑕点,应分段:
两个积分都发散(),故原积分发散。原”计算”得到 (负数)显然荒谬,因被积函数恒正。
# 陷阱 2 反例:∫_{-1}^1 1/x² dx
import numpy as np
from scipy.integrate import quad
# 错误做法:直接用 N-L 公式
print("错误做法:[-1/x]_{-1}^1 = -1 - 1 = -2 (荒谬,被积函数恒正!)")
# 正确做法:分段处理瑕点
val_pos, _ = quad(lambda x: 1/x**2, 1e-10, 1)
val_neg, _ = quad(lambda x: 1/x**2, -1, -1e-10)
print(f"\n∫_{-1}^{-ε} 1/x² dx ≈ {val_neg:.4f} (发散)")
print(f"∫_{ε}^1 1/x² dx ≈ {val_pos:.4f} (发散)")
print("两个单侧极限都发散 → 原积分发散")
8.3 陷阱 3:绝对收敛 vs 条件收敛混淆
错误:对条件收敛的积分随意交换积分顺序或重排,导致不同结果。
正确:Fubini 定理、变量替换定理、分部积分的多种”积分换序”操作都要求绝对可积。条件收敛积分必须显式保留原顺序。
反例: 与反序结果不同(见 4.6 节)。
8.4 陷阱 4:变量替换忽略 Jacobian
错误(多元):写 ,漏掉 。
正确:
反例:极坐标 ,若漏掉 ,计算 会得到 (错误),正确值为 。
# 陷阱 4 反例:极坐标漏 Jacobian
import numpy as np
from scipy.integrate import dblquad
# 真值:单位圆面积 = π
true_val = np.pi
# 错误(漏 r):∫_0^{2π} ∫_0^1 1 dr dθ = 2π
wrong = dblquad(lambda r, theta: 1, 0, 2*np.pi, 0, 1)
print(f"漏 Jacobian: {wrong[0]:.6f} (错误,应为 π ≈ {true_val:.6f})")
# 正确(带 r):∫_0^{2π} ∫_0^1 r dr dθ = π
correct = dblquad(lambda r, theta: r, 0, 2*np.pi, 0, 1)
print(f"带 Jacobian: {correct[0]:.6f} (正确)")
print(f"误差: {abs(correct[0] - true_val):.2e}")
8.5 陷阱 5:Fubini 定理条件忽略
错误:对不绝对可积的函数应用 Fubini 定理,得到两个不等的累次积分。
正确:必须先验证 。若 ,可用 Tonelli 定理(允许无穷值)。
8.6 陷阱 6:Riemann 可积性误判
错误:认为”有界 + 间断点可数”是 Riemann 可积的充要条件。
正确:充要条件是 Lebesgue 判据:有界 + 间断点集测度为零。可数集测度为零(充分),但反之不真(Cantor 集不可数但测度为零,函数在 Cantor 集上间断仍可 Riemann 可积)。
8.7 陷阱 7:数值积分的奇异性
错误:用标准 quad 计算 不指定 处的奇异性,得到错误结果。
正确:虽然 (可去间断),但数值积分仍需指定或预处理。对不可去奇异性(如 )需用变量替换或专门算法。
# 陷阱 7:sin(x)/x 在 0 处的可去奇异性
import numpy as np
from scipy.integrate import quad
# 错误:直接积分(可能警告或精度损失)
val1, err1 = quad(lambda x: np.sin(x)/x, 0, 1)
print(f"直接 quad: {val1:.10f} (误差估计 {err1:.2e})")
# 正确:指定可去奇点,或用 sinc 函数
val2, err2 = quad(lambda x: np.sinc(x/np.pi), 0, 1) # numpy.sinc 归一化
print(f"用 sinc(x/π): {val2:.10f}")
# 严格做法:用 sympy 符号计算
import sympy as sp
x = sp.Symbol('x')
val_exact = sp.integrate(sp.sin(x)/x, (x, 0, 1))
print(f"sympy 精确值: {val_exact} = {float(val_exact):.10f}")
第 9 章 工程实践:数值积分方法
理论上的 Newton-Leibniz 公式 要求被积函数 存在初等原函数 。然而工程实践中,大量被积函数的原函数无法用初等函数表示(如 、、),或者 仅以离散采样点形式给出。此时必须依赖数值积分(numerical quadrature)方法。
本章系统介绍四种工业级数值积分方法:Gauss-Legendre 求积、Romberg 积分、自适应 Simpson 积分、高维 Monte Carlo 与稀疏网格,并给出 Python 实现与误差分析。
9.1 Newton-Cotes 公式族回顾
核心思想:用等距节点 处的 Lagrange 插值多项式 逼近 ,然后对 积分。
| 公式 | 节点数 | 代数精度 | 误差阶 |
|---|---|---|---|
| 矩形法(中点) | 1 | 1 | |
| 梯形法 | 2 | 1 | |
| Simpson 法 | 3 | 3 | |
| Simpson 3/8 法 | 4 | 3 | |
| Boole 法 | 5 | 5 |
代数精度(algebraic degree of accuracy):若公式对一切次数 的多项式精确成立,而对某个 次多项式不精确,则称精度为 。
# Newton-Cotes 公式族实现与对比
import numpy as np
def midpoint(f, a, b, n=100):
"""复合中点法:代数精度 1,误差 O(h^2)"""
h = (b - a) / n
xs = a + (np.arange(n) + 0.5) * h
return h * np.sum(f(xs))
def trapezoid(f, a, b, n=100):
"""复合梯形法:代数精度 1,误差 O(h^2)"""
h = (b - a) / n
xs = a + np.arange(n + 1) * h
return h * (0.5 * f(xs[0]) + np.sum(f(xs[1:-1])) + 0.5 * f(xs[-1]))
def simpson(f, a, b, n=100):
"""复合 Simpson 法:代数精度 3,误差 O(h^4),要求 n 为偶数"""
if n % 2 == 1:
n += 1
h = (b - a) / n
xs = a + np.arange(n + 1) * h
return h / 3 * (f(xs[0]) + 4 * np.sum(f(xs[1:n:2])) +
2 * np.sum(f(xs[2:n-1:2])) + f(xs[n]))
def boole(f, a, b, n=100):
"""复合 Boole 法:代数精度 5,误差 O(h^6),要求 n 为 4 的倍数"""
if n % 4 != 0:
n += 4 - n % 4
h = (b - a) / n
xs = a + np.arange(n + 1) * h
s = 7 * (f(xs[0]) + f(xs[-1]))
s += 32 * np.sum(f(xs[1:n:2]) + f(xs[3:n:2]))
s += 12 * np.sum(f(xs[2:n:2]))
return 2 * h / 45 * s
# 验证:∫_0^1 e^x dx = e - 1 ≈ 1.718281828459045
import math
f = math.exp
exact = math.e - 1
for n in [10, 100, 1000, 10000]:
print(f"n={n:5d} mid={midpoint(f,0,1,n):.12f} "
f"trap={trapezoid(f,0,1,n):.12f} "
f"simp={simpson(f,0,1,n):.12f} "
f"bool={boole(f,0,1,n):.12f}")
print(f"exact = {exact:.12f}")
Runge 现象:当节点数 时,高阶 Newton-Cotes 公式(如 )在区间端点附近会出现剧烈振荡,误差不降反升。因此实际中避免使用高阶 Newton-Cotes,改用低阶复合公式或 Gauss 求积。
9.2 Gauss-Legendre 求积
核心思想:放弃等距节点约束,通过选择最优节点 与权重 ,使公式对尽可能高次的多项式精确成立。
点 Gauss-Legendre 公式具有 阶代数精度 — 这是 个节点能达到的理论上限。
节点选取:Gauss 节点为 次 Legendre 多项式 的零点,均在 内。
权重公式:。
对一般区间 ,通过线性变换 :
# Gauss-Legendre 求积实现
import numpy as np
from numpy.polynomial.legendre import leggauss
def gauss_legendre(f, a, b, n=5):
"""
n 点 Gauss-Legendre 求积,代数精度 2n-1
:param f: 被积函数
:param a, b: 积分下限上限
:param n: 节点数
:return: 积分近似值
"""
# 获取 [-1,1] 上的节点与权重
nodes, weights = leggauss(n)
# 线性变换至 [a,b]
mid = 0.5 * (a + b)
half = 0.5 * (b - a)
x_k = half * nodes + mid
return half * np.sum(weights * f(x_k))
# 验证:∫_0^1 x^9 dx = 1/10 (5 点 Gauss 精度为 9,应精确)
f = lambda x: x**9
print(f"5 点 Gauss: {gauss_legendre(f, 0, 1, n=5):.15f} (精确值 0.1)")
print(f"误差: {abs(gauss_legendre(f, 0, 1, n=5) - 0.1):.2e}")
# 验证:∫_0^1 x^11 dx = 1/12 (5 点精度为 9,应不精确;6 点精度 11,应精确)
f11 = lambda x: x**11
print(f"5 点 Gauss: {gauss_legendre(f11, 0, 1, n=5):.15f} (精确值 {1/12:.15f})")
print(f"6 点 Gauss: {gauss_legendre(f11, 0, 1, n=6):.15f} (精确值 {1/12:.15f})")
# 实战:∫_{-1}^1 e^x dx = e - 1/e
import math
fexp = lambda x: np.exp(x)
exact = math.e - 1/math.e
for n in [2, 3, 4, 5, 10]:
val = gauss_legendre(fexp, -1, 1, n=n)
print(f"n={n:2d}: {val:.12f} 误差 {abs(val - exact):.2e}")
复合 Gauss 求积:将 分为 个子区间,每个子区间用 点 Gauss,总误差 。
# 复合 Gauss-Legendre 求积
def composite_gauss(f, a, b, m=10, n=4):
"""
将 [a,b] 分为 m 个子区间,每个子区间用 n 点 Gauss
:param m: 子区间数
:param n: 每子区间节点数
"""
nodes, weights = leggauss(n)
h = (b - a) / m
total = 0.0
for i in range(m):
ai = a + i * h
bi = ai + h
mid = 0.5 * (ai + bi)
half = 0.5 * (bi - ai)
x_k = half * nodes + mid
total += half * np.sum(weights * f(x_k))
return total
# 对比:∫_0^π sin(x) dx = 2
fsin = lambda x: np.sin(x)
exact = 2.0
print("复合 Gauss (m 子区间 × n 点):")
for m, n in [(1, 4), (2, 4), (4, 2), (10, 2), (10, 4), (100, 4)]:
val = composite_gauss(fsin, 0, np.pi, m=m, n=n)
print(f" m={m:3d}, n={n}: {val:.12f} 误差 {abs(val - exact):.2e}")
9.3 Romberg 积分
核心思想:利用 Richardson 外推加速梯形法的收敛速度。
梯形法的 Euler-Maclaurin 展开给出了误差的渐近级数:
其中 为真值, 为与 无关的常数。通过组合不同步长的梯形结果,可逐次消去 项,得到 的高阶方法。
Romberg 表:
其中 为第 次二分后的梯形值, 为第 次外推后的值, 给出 阶精度。
# Romberg 积分实现
import numpy as np
def trapezoid_recursive(f, a, b, n):
"""
递推梯形法:利用前一次结果 T_n 计算 T_{2n},只需新增中点
T_{2n} = 0.5 * T_n + h/2 * sum_{i=1}^{n} f(a + (2i-1)*h/2)
"""
if n == 0:
return 0.5 * (b - a) * (f(a) + f(b))
# T_n -> T_{2n}
h = (b - a) / (2 ** n)
# 新增的 n 个中点
new_points = np.array([a + (2 * k - 1) * h for k in range(1, 2 ** (n - 1) + 1)])
return 0.5 * trapezoid_recursive(f, a, b, n - 1) + h * np.sum(f(new_points))
def romberg(f, a, b, max_iter=10, tol=1e-12):
"""
Romberg 积分:基于梯形法的 Richardson 外推
:return: (积分值, Romberg 表, 实际迭代次数)
"""
R = np.zeros((max_iter, max_iter))
R[0, 0] = 0.5 * (b - a) * (f(a) + f(b))
for k in range(1, max_iter):
# 第 k 行第一列:梯形法二分
h = (b - a) / (2 ** k)
# 新增中点
new_xs = np.array([a + (2 * i - 1) * h for i in range(1, 2 ** (k - 1) + 1)])
R[k, 0] = 0.5 * R[k - 1, 0] + h * np.sum(f(new_xs))
# Richardson 外推
for j in range(1, k + 1):
R[k, j] = R[k, j - 1] + (R[k, j - 1] - R[k - 1, j - 1]) / (4 ** j - 1)
# 收敛判据
if k > 0 and abs(R[k, k] - R[k - 1, k - 1]) < tol:
return R[k, k], R[:k + 1, :k + 1], k + 1
return R[max_iter - 1, max_iter - 1], R, max_iter
# 验证:∫_0^1 e^x dx = e - 1
import math
f = np.vectorize(math.exp)
val, table, iters = romberg(f, 0, 1, max_iter=8)
print(f"Romberg 结果: {val:.15f}")
print(f"真值: {math.e - 1:.15f}")
print(f"误差: {abs(val - (math.e - 1)):.2e}")
print(f"迭代次数: {iters}")
print("\nRomberg 表 (前 5 行):")
for i in range(min(5, iters)):
print(" " + " ".join(f"{table[i, j]:.10f}" for j in range(i + 1)))
Romberg 的优势:在光滑函数上,Romberg 以极少的函数求值即可达到机器精度;但对非光滑函数(如含 项),Euler-Maclaurin 展开不成立,外推失效。
9.4 自适应积分
核心思想:在函数变化剧烈处加密采样,在平缓处稀疏采样,以最少函数求值达到给定精度。
自适应 Simpson 算法:
- 在 上用 Simpson 法计算 ;
- 在 与 ()上各用 Simpson,得 ;
- 误差估计 时接受,否则递归二分。
# 自适应 Simpson 积分
def adaptive_simpson(f, a, b, tol=1e-10, max_depth=50):
"""
自适应 Simpson 积分:在函数变化剧烈处自动加密
:param tol: 局部误差容限
:param max_depth: 最大递归深度
"""
def _simpson(a, b, fa, fm, fb):
return (b - a) / 6 * (fa + 4 * fm + fb)
def _recurse(a, b, fa, fm, fb, whole, tol, depth):
m = (a + b) / 2
lm = (a + m) / 2
rm = (m + b) / 2
flm = f(lm)
frm = f(rm)
left = _simpson(a, m, fa, flm, fm)
right = _simpson(m, b, fm, frm, fb)
# 误差估计:Simpson 误差 ~ |S - (Sl + Sr)| / 15
if depth <= 0 or abs(left + right - whole) <= 15 * tol:
return left + right + (left + right - whole) / 15
return (_recurse(a, m, fa, flm, fm, left, tol / 2, depth - 1) +
_recurse(m, b, fm, frm, fb, right, tol / 2, depth - 1))
fa, fb = f(a), f(b)
fm = f((a + b) / 2)
whole = _simpson(a, b, fa, fm, fb)
return _recurse(a, b, fa, fm, fb, whole, tol, max_depth)
# 实战:∫_0^10 (1 + 100*x^2)^{-1} dx = arctan(10)/10 ≈ 0.156412
# 该函数在 x=0 附近剧烈变化,自适应积分优势明显
import math
f = lambda x: 1 / (1 + 100 * x**2)
exact = math.atan(10) / 10
val_adapt = adaptive_simpson(f, 0, 10, tol=1e-12)
print(f"自适应 Simpson: {val_adapt:.12f}")
print(f"真值: {exact:.12f}")
print(f"误差: {abs(val_adapt - exact):.2e}")
# 对比:复合 Simpson 需要更多点才能达到同等精度
def simpson_n(f, a, b, n):
if n % 2 == 1:
n += 1
h = (b - a) / n
xs = [a + i * h for i in range(n + 1)]
s = f(xs[0]) + f(xs[-1])
s += 4 * sum(f(xs[i]) for i in range(1, n, 2))
s += 2 * sum(f(xs[i]) for i in range(2, n - 1, 2))
return s * h / 3
for n in [100, 1000, 10000, 100000]:
val = simpson_n(f, 0, 10, n)
print(f" 复合 Simpson n={n:6d}: {val:.12f} 误差 {abs(val - exact):.2e}")
9.5 高维积分:Monte Carlo 与稀疏网格
高维积分 中,Newton-Cotes 与 Gauss 求积的节点数随维数 指数增长(维度灾难)。Monte Carlo 方法的误差 与维数无关,在 时显著优于确定方法。
Monte Carlo 估计量:
由中心极限定理,,其中 。
方差缩减技术:
- 重要性采样(importance sampling):从 采样,估计 ;
- 分层抽样(stratified sampling):将区域分层,层内独立采样;
- 拉丁超立方(Latin Hypercube):每维独立分层,避免聚集;
- 准 Monte Carlo(QMC):用 Sobol、Halton 等低 discrepancy 序列,误差 。
# Monte Carlo 与 QMC 高维积分对比
import numpy as np
from scipy.stats import qmc
# 测试函数:∫_{[0,1]^d} ∏_{i=1}^d (1 + x_i) dx = 2^d
def integrand(xs):
"""d 维被积函数:∏(1 + x_i)"""
return np.prod(1 + xs, axis=-1)
# Monte Carlo 估计
def monte_carlo(f, d, N):
xs = np.random.uniform(0, 1, size=(N, d))
return np.mean(f(xs))
# QMC 估计 (Sobol 序列)
def qmc_sobol(f, d, N):
sampler = qmc.Sobol(d=d, scramble=True)
xs = sampler.random_base2(m=int(np.log2(N)))
return np.mean(f(xs))
# 测试:5 维积分,真值 2^5 = 32
d = 5
exact = 2 ** d
print(f"d={d}, 真值 = {exact}")
for N in [1024, 8192, 65536]:
mc = monte_carlo(integrand, d, N)
qmc_val = qmc_sobol(integrand, d, N)
print(f" N={N:6d} MC={mc:.4f} 误差 {abs(mc-exact):.2e} | "
f"QMC={qmc_val:.4f} 误差 {abs(qmc_val-exact):.2e}")
# 重要性采样示例:∫_0^∞ e^{-x^2} dx = √π/2
# 直接采样困难(无穷区间),用 e^{-x} 作为提议分布
def importance_sampling_gaussian(N=100000):
"""
用 N(λ=1) 指数分布作为提议,采样 ∫_0^∞ e^{-x^2} dx
e^{-x^2} / e^{-x} = e^{x - x^2}
"""
from scipy.stats import expon
xs = expon.rvs(scale=1, size=N)
weights = np.exp(xs - xs**2)
return np.mean(weights)
val = importance_sampling_gaussian()
print(f"\n重要性采样 ∫_0^∞ e^{{-x²}} dx ≈ {val:.6f} (真值 {np.sqrt(np.pi)/2:.6f})")
9.6 工程取舍与选型决策
flowchart TD
A[数值积分任务] --> B{被积函数光滑?}
B -- 是 --> C{维数 d?}
B -- 否 --> D{间断/奇异点已知?}
D -- 是 --> E[分段积分 + Gauss]
D -- 否 --> F[自适应 Simpson]
C -- d=1 --> G{需要机器精度?}
C -- 2 ≤ d ≤ 3 --> H[复合 Gauss 或 张量积]
C -- d ≥ 4 --> I[Monte Carlo / QMC]
G -- 是 --> J[Romberg]
G -- 否 --> K[复合 Simpson]
J --> L{外推收敛?}
L -- 是 --> M[接受结果]
L -- 否 --> N[改用 Gauss-Kronrod]
K --> M
H --> M
I --> M
E --> M
F --> M
N --> M
工程实践要点:
- 先尝试 sympy 符号积分:若能求得闭式解,优先使用;
- 1 维光滑函数:Romberg 或 Gauss-Kronrod(scipy 的
quad默认); - 1 维含奇异点:自适应积分 + 指定奇异点位置;
- 2-3 维:张量积 Gauss 或
scipy.integrate.dblquad/tplquad; - 4+ 维:Monte Carlo 或 QMC(Sobol 序列);
- 振荡积分(, 大):用 Levin 算法或 Filon 求积;
- 周期函数:梯形法在中点处收敛速度达 ,远优于 Simpson(源自 Euler-Maclaurin 级数所有项消失)。
# 振荡积分 Filon 求积示例
def filon_sine(f, a, b, omega, n=1001):
"""
Filon 求积:计算 ∫_a^b f(x) sin(ωx) dx
适用于 ω 大的振荡积分
"""
if n % 2 == 0:
n += 1
h = (b - a) / (n - 1)
xs = np.linspace(a, b, n)
fs = f(xs)
theta = omega * h
# Filon 系数
if abs(theta) < 1e-10:
alpha = 2/3
beta = 1/3
gamma = 1/3
else:
sin_t = np.sin(theta)
cos_t = np.cos(theta)
sin2 = np.sin(2 * theta)
alpha = (theta**2 + theta * sin_t * cos_t - 2 * sin_t**2) / theta**3
beta = 2 * (theta * (1 + cos_t**2) - sin2) / theta**3
gamma = 4 * (sin_t * cos_t - theta) / theta**3
s = alpha * (fs[0] * np.sin(omega * xs[0]) +
fs[-1] * np.sin(omega * xs[-1]))
s += beta * np.sum(fs[1:-1:2] * np.sin(omega * xs[1:-1:2]))
s += gamma * np.sum(fs[2:-1:2] * np.sin(omega * xs[2:-1:2]))
return s * h
# 验证:∫_0^1 cos(x) sin(100x) dx
import numpy as np
f = np.cos
omega = 100
val_filon = filon_sine(f, 0, 1, omega, n=1001)
# 精确值:∫_0^1 cos(x) sin(100x) dx
# = 0.5 * [sin(101x)/101 + sin(99x)/99]_0^1
exact = 0.5 * (np.sin(101)/101 + np.sin(99)/99)
print(f"Filon: {val_filon:.10f}")
print(f"精确: {exact:.10f}")
print(f"误差: {abs(val_filon - exact):.2e}")
第 10 章 案例研究
本章通过三个工程案例,展示定积分在深度学习、科学计算与统计物理中的实际应用。每个案例从问题建模出发,推导至代码实现,最后给出性能分析与工程经验。
10.1 案例 1:PyTorch autograd 的反向传播积分
问题背景:深度学习中的损失函数常含期望形式 ,需用 mini-batch 的 Monte Carlo 积分估计。反向传播通过链式法则计算 ,本质上是对积分的梯度。
理论:若 ,则
积分与梯度的可交换性源于 Leibniz 积分规则,要求 对 连续可微且被积函数被可积函数控制(Lebesgue 控制收敛定理)。
# 案例 1:PyTorch 反向传播中的积分计算
import torch
import torch.nn as nn
# 场景:逻辑回归的负对数似然损失
# L(θ) = -∫ [y log σ(θ·x) + (1-y) log(1 - σ(θ·x))] p(x,y) dx,y
# 用 mini-batch Monte Carlo 估计梯度
class LogisticRegression(nn.Module):
def __init__(self, dim):
super().__init__()
self.theta = nn.Parameter(torch.zeros(dim))
def forward(self, x):
return torch.sigmoid(x @ self.theta)
# 生成合成数据
torch.manual_seed(42)
n_samples = 10000
dim = 5
X = torch.randn(n_samples, dim)
true_theta = torch.tensor([1.0, -0.5, 0.8, -0.3, 0.6])
probs = torch.sigmoid(X @ true_theta)
y = (torch.rand(n_samples) < probs).float().unsqueeze(1)
# 训练:用积分视角理解 SGD
# 每个 batch 是对 E[∇ℓ] 的一次 Monte Carlo 估计
model = LogisticRegression(dim)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
batch_size = 64
n_epochs = 10
for epoch in range(n_epochs):
indices = torch.randperm(n_samples)
total_loss = 0.0
n_batches = 0
for i in range(0, n_samples, batch_size):
# mini-batch = Monte Carlo 积分样本
batch_x = X[indices[i:i+batch_size]]
batch_y = y[indices[i:i+batch_size]]
# 损失 = (1/N) Σ ℓ(x_i, y_i; θ) ≈ E[ℓ]
preds = model(batch_x)
loss = nn.functional.binary_cross_entropy(preds, batch_y)
# 反向传播:计算 ∇θ L,即 ∇∫ ℓ p dx 的 Monte Carlo 估计
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
n_batches += 1
print(f"Epoch {epoch+1}: 平均损失 = {total_loss / n_batches:.4f}")
print(f"\n学习到的 θ: {model.theta.data}")
print(f"真值 θ: {true_theta}")
print(f"误差: {(model.theta.data - true_theta).norm():.4f}")
积分视角的 SGD 分析:
| 概念 | 数学表述 | 工程对应 |
|---|---|---|
| 真损失 | 全数据集平均损失 | |
| Mini-batch 估计 | $\hat{L}_B = \frac{1}{ | B |
| 梯度 | 真梯度 | |
| 随机梯度 | batch 梯度 | |
| 估计方差 | batch 越大方差越小 |
重参数化技巧(Reparameterization Trick):VAE 中需对 求梯度,但采样不可微。通过 (),将积分的梯度转化为确定变换的梯度:
# VAE 重参数化技巧:化随机积分为可微计算
import torch
class VAEEncoder(nn.Module):
def __init__(self, input_dim, latent_dim):
super().__init__()
self.fc_mu = nn.Linear(input_dim, latent_dim)
self.fc_logvar = nn.Linear(input_dim, latent_dim)
def forward(self, x):
mu = self.fc_mu(x)
logvar = self.fc_logvar(x)
# 重参数化:z = μ + σ·ε,ε ~ N(0,I)
# E_{z~q}[f(z)] ≈ (1/N) Σ f(μ + σ·ε_i)
# 梯度可经 μ, σ 反传
std = torch.exp(0.5 * logvar)
eps = torch.randn_like(std)
z = mu + std * eps
return z, mu, logvar
# 重构损失:积分 E_{z~q}[log p(x|z)] 的 Monte Carlo 估计
def vae_loss(recon_x, x, mu, logvar):
BCE = nn.functional.binary_cross_entropy(recon_x, x, reduction='sum')
# KL 散度有闭式解:D_KL(q||p) = -0.5 Σ (1 + log σ² - μ² - σ²)
KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
return BCE + KLD
# 一个完整的 VAE 训练 step
input_dim, latent_dim = 784, 20
encoder = VAEEncoder(input_dim, latent_dim)
decoder = nn.Sequential(
nn.Linear(latent_dim, 400),
nn.ReLU(),
nn.Linear(400, input_dim),
nn.Sigmoid()
)
optimizer = torch.optim.Adam(
list(encoder.parameters()) + list(decoder.parameters()), lr=1e-3)
# 假装 x 是 MNIST 的一张图
x = torch.bernoulli(torch.full((32, input_dim), 0.5))
z, mu, logvar = encoder(x)
recon_x = decoder(z)
loss = vae_loss(recon_x, x, mu, logvar)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"VAE loss: {loss.item():.2f} (含重构 + KL)")
10.2 案例 2:scipy.integrate 工程实战
scipy.integrate 是 Python 生态最成熟的积分库,封装了 QUADPACK 的 Fortran 实现。本案例展示其高级用法。
# 案例 2:scipy.integrate 高级用法
import numpy as np
from scipy import integrate
# (1) 一维积分:QUADPACK 的 QAGS 算法(自适应 Gauss-Kronrod 21 点 + 外推)
# 计算 Fresnel 积分 S(x) = ∫_0^x sin(πt²/2) dt
def fresnel_s(x):
"""Fresnel 正弦积分"""
val, err = integrate.quad(lambda t: np.sin(np.pi * t**2 / 2), 0, x)
return val, err
for x in [0.5, 1.0, 2.0, 5.0, np.inf]:
s, e = fresnel_s(x)
print(f"S({x}) = {s:.8f} (误差估计 {e:.2e})")
# (2) 含奇异点的积分:∫_0^1 x^{-1/2} e^x dx
# 在 x=0 处有可积奇异性
val, err = integrate.quad(lambda x: x**(-0.5) * np.exp(x), 0, 1,
points=[0]) # 指定奇异点
print(f"\n含奇异点积分: {val:.10f} (误差 {err:.2e})")
# (3) 含参数的积分:Gamma 函数 Γ(a) = ∫_0^∞ t^{a-1} e^{-t} dt
def gamma_func(a):
return integrate.quad(lambda t: t**(a-1) * np.exp(-t), 0, np.inf)[0]
import math
for a in [0.5, 1, 1.5, 2, 5, 10]:
val = gamma_func(a)
exact = math.gamma(a)
print(f"Γ({a}) = {val:.8f} 精确 {exact:.8f} 误差 {abs(val-exact):.2e}")
# (4) 二重积分:∫_0^1 ∫_0^1 x² e^{-xy} dx dy
val, err = integrate.dblquad(
lambda y, x: x**2 * np.exp(-x * y), # 注意参数顺序:y 在前
0, 1, # x 范围
0, 1 # y 范围(可为 x 的函数)
)
print(f"\n二重积分: {val:.10f} (误差 {err:.2e})")
# (5) 三重积分:球体积 V = ∫∫∫_B 1 dV, B = {x²+y²+z² ≤ 1}
# 用球坐标:V = ∫_0^{2π} ∫_0^π ∫_0^1 ρ² sin(φ) dρ dφ dθ
val, err = integrate.tplquad(
lambda z, y, x: 1.0,
-1, 1, # x 范围
lambda x: -np.sqrt(1 - x**2), # y 下界
lambda x: np.sqrt(1 - x**2), # y 上界
lambda x, y: -np.sqrt(1 - x**2 - y**2), # z 下界
lambda x, y: np.sqrt(1 - x**2 - y**2), # z 上界
)
print(f"球体积: {val:.10f} (精确 {4/3*np.pi:.10f}) 误差 {abs(val - 4/3*np.pi):.2e}")
# (6) ODE 系统求解:洛伦兹吸引子
def lorenz(t, state, sigma=10, rho=28, beta=8/3):
x, y, z = state
return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]
from scipy.integrate import solve_ivp
t_span = (0, 40)
t_eval = np.linspace(*t_span, 10000)
sol = solve_ivp(lorenz, t_span, [1, 1, 1], t_eval=t_eval, method='RK45',
rtol=1e-9, atol=1e-12)
print(f"\n洛伦兹方程积分: {sol.success}, {len(sol.t)} 时间步, "
f"状态范围 [{sol.y.min():.2f}, {sol.y.max():.2f}]")
# (7) 高维积分对比:scipy vs Monte Carlo
# 计算 6 维正态分布的归一化常数(理论上为 1)
from scipy.stats import multivariate_normal
mean = np.zeros(6)
cov = np.eye(6)
rv = multivariate_normal(mean, cov)
# scipy 的 nquad(维度灾难)
def integrand_6d(x1, x2, x3, x4, x5, x6):
return rv.pdf([x1, x2, x3, x4, x5, x6])
# 范围 ±5σ
limits = [(-5, 5)] * 6
val_q, err_q = integrate.nquad(integrand_6d, limits,
opts={'limit': 30})
print(f"\n6 维正态归一化(nquad): {val_q:.6f} (应=1) 误差 {err_q:.2e}")
# Monte Carlo 对比
N = 1000000
samples = np.random.uniform(-5, 5, size=(N, 6))
vals = rv.pdf(samples)
val_mc = 10**6 * np.mean(vals) # 体积 10^6 × 均值
print(f"6 维正态归一化(MC N={N}): {val_mc:.6f} 误差 ~{abs(val_mc-1):.2e}")
工程经验:
quad默认 QAGS 算法,适用于大多数光滑函数;- 对振荡积分,设置
limit=200增加子区间数; - 对奇异积分,显式指定
points参数告知奇异点; - 对高维积分, 时优先用 Monte Carlo 或 QMC;
- ODE 求解选
RK45(默认)或DOP853(高精度);刚性系统用Radau或BDF。
10.3 案例 3:Monte Carlo 积分在金融与物理中的应用
10.3.1 期权定价(Black-Scholes-Merton 模型)
欧式看涨期权的理论价格为:
其中 ,。
# 案例 3.1:Monte Carlo 期权定价
import numpy as np
def black_scholes_call(S0, K, T, r, sigma, n_paths=1000000):
"""
Monte Carlo 定价欧式看涨期权
:param S0: 当前股价
:param K: 行权价
:param T: 到期时间(年)
:param r: 无风险利率
:param sigma: 波动率
:param n_paths: 模拟路径数
"""
Z = np.random.standard_normal(n_paths)
# 风险中性测度下的终值
ST = S0 * np.exp((r - 0.5 * sigma**2) * T + sigma * np.sqrt(T) * Z)
# 收益 = max(ST - K, 0)
payoff = np.maximum(ST - K, 0)
# 折现期望
C = np.exp(-r * T) * np.mean(payoff)
# 标准误差
se = np.exp(-r * T) * np.std(payoff) / np.sqrt(n_paths)
return C, se
# 参数:S0=100, K=100, T=1, r=5%, σ=20%
S0, K, T, r, sigma = 100, 100, 1, 0.05, 0.20
C_mc, se = black_scholes_call(S0, K, T, r, sigma, n_paths=10000000)
print(f"Monte Carlo 期权价格: {C_mc:.6f} ± {1.96*se:.6f} (95% CI)")
# Black-Scholes 闭式解对照
from scipy.stats import norm
d1 = (np.log(S0/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
C_bs = S0 * norm.cdf(d1) - K * np.exp(-r*T) * norm.cdf(d2)
print(f"Black-Scholes 闭式解: {C_bs:.6f}")
print(f"偏差: {abs(C_mc - C_bs):.6f}")
# 方差缩减:对偶变量法(antithetic variates)
def bs_call_antithetic(S0, K, T, r, sigma, n_paths=5000000):
"""对偶变量法:同时用 Z 和 -Z,方差减半"""
Z = np.random.standard_normal(n_paths // 2)
ST1 = S0 * np.exp((r - 0.5*sigma**2)*T + sigma*np.sqrt(T)*Z)
ST2 = S0 * np.exp((r - 0.5*sigma**2)*T - sigma*np.sqrt(T)*Z)
payoff = 0.5 * (np.maximum(ST1 - K, 0) + np.maximum(ST2 - K, 0))
return np.exp(-r*T) * np.mean(payoff)
C_av = bs_call_antithetic(S0, K, T, r, sigma)
print(f"对偶变量法: {C_av:.6f} 偏差 {abs(C_av - C_bs):.6f}")
10.3.2 统计物理:Ising 模型的配分函数
二维 Ising 模型的配分函数:
求和遍历 个自旋构型,大 下无法枚举。Metropolis 算法通过 Markov 链 Monte Carlo 采样典型构型,估算热力学量。
# 案例 3.2:Ising 模型 Metropolis 算法
import numpy as np
def ising_metropolis(L=20, T=2.27, J=1.0, n_steps=100000, n_thermal=10000):
"""
二维 Ising 模型 Metropolis 采样
:param L: 格子边长
:param T: 温度(k_B = 1)
:param J: 耦合常数
:return: 能量与磁化轨迹
"""
beta = 1.0 / T
# 随机初始构型
spins = np.random.choice([-1, 1], size=(L, L))
def energy(s):
"""周期边界下的总能量"""
return -J * (np.sum(s * np.roll(s, 1, axis=0)) +
np.sum(s * np.roll(s, 1, axis=1)))
energies = []
magnets = []
for step in range(n_steps):
# 随机选一个格点
i, j = np.random.randint(0, L, 2)
# 计算翻转能量变化 ΔE
neighbors = (spins[(i-1) % L, j] + spins[(i+1) % L, j] +
spins[i, (j-1) % L] + spins[i, (j+1) % L])
dE = 2 * J * spins[i, j] * neighbors
# Metropolis 接受准则
if dE <= 0 or np.random.rand() < np.exp(-beta * dE):
spins[i, j] *= -1
if step >= n_thermal:
energies.append(energy(spins))
magnets.append(np.sum(spins))
return np.array(energies), np.array(magnets)
# 模拟临界温度附近的 Ising 模型
# 解析临界温度 T_c = 2/ln(1+√2) ≈ 2.269
T_c = 2.0 / np.log(1 + np.sqrt(2))
print(f"二维 Ising 临界温度 T_c = {T_c:.4f}")
for T in [1.5, 2.0, 2.27, 2.5, 3.5]:
E, M = ising_metropolis(L=16, T=T, n_steps=50000, n_thermal=10000)
print(f"T={T:.2f}: <E>/N = {E.mean()/(16*16):.4f}, "
f"<|M|>/N = {np.abs(M).mean()/(16*16):.4f}, "
f"C = {E.var()/(T**2 * 16*16):.4f}")
10.3.3 贝叶斯推断:后验分布的积分
贝叶斯推断中,后验期望 通常无闭式解,需用 MCMC。
# 案例 3.3:MCMC 贝叶斯推断 — 贝叶斯线性回归
import numpy as np
# 生成数据:y = 2x + 1 + ε, ε ~ N(0, 0.5²)
np.random.seed(42)
true_slope, true_intercept = 2.0, 1.0
n = 50
x = np.linspace(0, 10, n)
y = true_slope * x + true_intercept + np.random.normal(0, 0.5, n)
# Metropolis-Hastings 采样后验 p(slope, intercept | x, y)
def log_posterior(slope, intercept, x, y, sigma=0.5):
"""对数后验(正态似然 + 平坦先验)"""
pred = slope * x + intercept
resid = y - pred
return -0.5 * np.sum(resid**2) / sigma**2
def metropolis(x, y, n_samples=20000, proposal_std=0.05):
"""Metropolis-Hastings MCMC"""
samples = np.zeros((n_samples, 2))
# 起点
slope, intercept = 0.0, 0.0
log_p = log_posterior(slope, intercept, x, y)
accepted = 0
for i in range(n_samples):
# 对称提议:高斯随机游走
new_slope = slope + np.random.normal(0, proposal_std)
new_intercept = intercept + np.random.normal(0, proposal_std)
new_log_p = log_posterior(new_slope, new_intercept, x, y)
# 接受概率
if np.log(np.random.rand()) < new_log_p - log_p:
slope, intercept, log_p = new_slope, new_intercept, new_log_p
accepted += 1
samples[i] = [slope, intercept]
print(f"接受率: {accepted/n_samples:.2f}")
return samples
samples = metropolis(x, y, n_samples=30000)
# 丢弃前 5000 作为 burn-in
post = samples[5000:]
print(f"\n后验均值:")
print(f" slope: {post[:, 0].mean():.4f} ± {post[:, 0].std():.4f} (真值 {true_slope})")
print(f" intercept: {post[:, 1].mean():.4f} ± {post[:, 1].std():.4f} (真值 {true_intercept})")
# 后验积分:通过样本均值估计 E[θ | x,y]
# 这是 Monte Carlo 积分对贝叶斯推断的直接应用
10.4 性能基准与可观测性
# 性能基准:不同积分方法在 ∫_0^1 e^x dx 上的对比
import numpy as np
import math
import timeit
from scipy.integrate import quad
f = math.exp
exact = math.e - 1
methods = {
'复合梯形 (n=1000)': lambda: sum(f(i/1000) for i in range(1001)) / 1000 + (f(1) - f(0))/(2*1000),
'复合 Simpson (n=1000)': lambda: (
(f(0) + f(1) + 4*sum(f(i/1000) for i in range(1, 1000, 2)) +
2*sum(f(i/1000) for i in range(2, 999, 2))) / 3000
),
'scipy.quad': lambda: quad(f, 0, 1)[0],
'numpy.vectorize + Simpson': lambda: np.trapz(np.exp(np.linspace(0, 1, 1001)), np.linspace(0, 1, 1001)),
}
print(f"{'方法':<30} {'结果':<18} {'误差':<12} {'耗时(μs)':<10}")
print("-" * 70)
for name, fn in methods.items():
t = timeit.timeit(fn, number=1000) / 1000 * 1e6
val = fn()
print(f"{name:<30} {val:<18.12f} {abs(val-exact):<12.2e} {t:<10.1f}")
关键观察:
scipy.quad通常以最少函数求值达到最高精度(QUADPACK 自适应);- 纯 Python 循环比 NumPy 向量化慢 10-100 倍;
- 高精度场景下,符号积分(sympy)比数值积分更可靠,但代价是速度;
- 工程实践中,先用 quad 试算,精度不够再换 sympy。
第 11 章 几何与物理应用
定积分的诞生本就源于几何度量与物理建模的需求。本章系统总结定积分在几何(面积、体积、弧长、侧面积)与物理(做功、质心、转动惯量、液体静压力、引力)中的标准应用,每个公式配 Python 数值验证。
11.1 平面图形面积
情形 1:曲线 与 ()在 之间围成的面积:
情形 2:极坐标曲线 在 之间扫过的扇形面积:
# 面积计算案例
import numpy as np
import sympy as sp
# 案例 1:y = x² 与 y = √x 围成的区域面积
x = sp.Symbol('x')
f = sp.sqrt(x) # 上
g = x**2 # 下
# 交点:x² = √x => x = 0, 1
intersections = sp.solve(f - g, x)
print(f"交点: {intersections}")
area = sp.integrate(f - g, (x, 0, 1))
print(f"面积 = ∫_0^1 (√x - x²) dx = {area} = {float(area):.6f}")
# 案例 2:心形线 r = 1 + cos(θ) 围成的面积
theta = sp.Symbol('theta')
r = 1 + sp.cos(theta)
area_cardioid = sp.integrate(sp.Rational(1, 2) * r**2, (theta, 0, 2*sp.pi))
print(f"心形线面积 = {sp.simplify(area_cardioid)} = {float(area_cardioid):.6f}")
# 解析结果应为 3π/2
# 案例 3:玫瑰线 r = cos(2θ) 一瓣的面积
r_rose = sp.cos(2*theta)
area_petal = sp.integrate(sp.Rational(1, 2) * r_rose**2, (theta, -sp.pi/4, sp.pi/4))
print(f"玫瑰线一瓣面积 = {sp.simplify(area_petal)} = {float(area_petal):.6f}")
11.2 立体体积
情形 1 — 截面法:已知立体在 处的截面面积 ,则体积:
情形 2 — 旋转体(圆盘法):曲线 绕 轴旋转一周:
情形 3 — 旋转体(圆环法):曲线绕 轴旋转:
更一般地,区域 绕 旋转的体积为:
Pappus 定理:平面区域 绕不穿过 的轴旋转的体积等于 ,其中 为区域质心到轴的距离, 为区域面积。
# 体积计算案例
import sympy as sp
x = sp.Symbol('x')
# 案例 1:y = sin(x) 在 [0, π] 绕 x 轴旋转
V1 = sp.integrate(sp.pi * sp.sin(x)**2, (x, 0, sp.pi))
print(f"sin(x) 旋转体体积 = {V1} = {float(V1):.6f}")
# 解析:π²/2
# 案例 2:圆 (x-2)² + y² = 1 绕 y 轴旋转(环面)
# 用圆环法:V = 2π ∫ x · 2√(1 - (x-2)²) dx, x ∈ [1, 3]
# 由 Pappus 定理:V = 2π · 2 · π = 4π²
V2_pappus = 4 * sp.pi**2
print(f"环面体积 (Pappus) = {V2_pappus} = {float(V2_pappus):.6f}")
# 数值验证
y = sp.Symbol('y')
# 解为 x = 2 ± √(1-y²),y ∈ [-1, 1]
# 体积 = π ∫ [(2+√(1-y²))² - (2-√(1-y²))²] dy
V2 = sp.integrate(sp.pi * ((2 + sp.sqrt(1 - y**2))**2 - (2 - sp.sqrt(1 - y**2))**2),
(y, -1, 1))
print(f"环面体积 (直接积分) = {sp.simplify(V2)} = {float(V2):.6f}")
# 案例 3:截面法 — 金字塔(底面正方形边长 a,高 h)
# A(x) = a² (1 - x/h)²
a, h = sp.symbols('a h', positive=True)
V3 = sp.integrate(a**2 * (1 - x/h)**2, (x, 0, h))
print(f"金字塔体积 = {sp.simplify(V3)} = {sp.Rational(1, 3)}·a²·h")
11.3 平面曲线弧长
曲线 ()的弧长:
参数曲线 ():
极坐标曲线 :
注:许多弧长积分无初等原函数,需数值计算。
# 弧长计算案例
import sympy as sp
from scipy.integrate import quad
import numpy as np
# 案例 1:抛物线 y = x² 在 [0, 1] 上的弧长
x = sp.Symbol('x')
f = x**2
ds = sp.sqrt(1 + sp.diff(f, x)**2)
print(f"被积函数: {ds}")
L_symbolic = sp.integrate(ds, (x, 0, 1))
print(f"符号积分: {L_symbolic}")
# 多数情况下无初等原函数,需数值计算
L_numeric, _ = quad(lambda t: np.sqrt(1 + (2*t)**2), 0, 1)
print(f"数值弧长: {L_numeric:.10f}")
# 案例 2:圆的周长 r = 1 (参数方程)
t = sp.Symbol('t')
x_c = sp.cos(t)
y_c = sp.sin(t)
L_circle = sp.integrate(sp.sqrt(sp.diff(x_c, t)**2 + sp.diff(y_c, t)**2),
(t, 0, 2*sp.pi))
print(f"\n圆周长 = {L_circle} = {float(L_circle):.6f}")
# 案例 3:心形线 r = 1 + cos(θ) 的周长
theta = sp.Symbol('theta')
r = 1 + sp.cos(theta)
ds_polar = sp.sqrt(r**2 + sp.diff(r, theta)**2)
L_cardioid = sp.integrate(ds_polar, (theta, 0, 2*sp.pi))
print(f"心形线周长 = {sp.simplify(L_cardioid)} = {float(L_cardioid):.6f}")
# 解析:8
11.4 旋转曲面侧面积
曲线 (,)绕 轴旋转形成的曲面面积:
# 侧面积案例:球面面积
import sympy as sp
x = sp.Symbol('x')
# 半圆 y = √(R² - x²), x ∈ [-R, R], 绕 x 轴旋转
R = sp.Symbol('R', positive=True)
f = sp.sqrt(R**2 - x**2)
ds = sp.sqrt(1 + sp.diff(f, x)**2)
S = sp.integrate(2 * sp.pi * f * ds, (x, -R, R))
print(f"球面面积 = {sp.simplify(S)}")
# 解析:4πR²
11.5 物理应用:变力做功
变力 沿 轴从 到 做的功:
# 案例:弹簧做功 — Hooke 定律 F = kx
import sympy as sp
x, k = sp.symbols('x k', positive=True)
F = k * x # 弹簧力
W = sp.integrate(F, (x, 0, x))
print(f"弹簧拉伸 x 距离做功 W = {W} = (1/2)kx²")
# 案例:火箭发射做功 — 万有引力 F = GMm/r²
r, M, m, G, R_earth = sp.symbols('r M m G R_earth', positive=True)
F_grav = G * M * m / r**2
W_grav = sp.integrate(F_grav, (r, R_earth, sp.oo))
print(f"逃逸到无穷远做功 W = {W_grav} = GMm/R_earth")
# 案例:抽水做功 — 圆柱形水箱
# 水箱半径 R,高 H,水面从顶降到 z 时,需将水提升 z 距离
# dW = ρg · πR² · dz · z
rho, g, H_tank = sp.symbols('rho g H', positive=True)
W_water = sp.integrate(rho * g * sp.pi * R**2 * x, (x, 0, H_tank))
print(f"抽干水箱做功 W = {sp.simplify(W_water)} = (1/2)ρgπR²H²")
11.6 质心与形心
质心公式(密度 ):
平面区域的形心():
# 质心计算案例
import sympy as sp
x = sp.Symbol('x')
# 案例:半圆 y = √(R² - x²), x ∈ [-R, R] 的形心
R = sp.Symbol('R', positive=True)
f = sp.sqrt(R**2 - x**2)
g = sp.Integer(0)
A = sp.integrate(f - g, (x, -R, R))
x_bar = sp.integrate(x * (f - g), (x, -R, R)) / A
y_bar = sp.integrate((f**2 - g**2), (x, -R, R)) / (2 * A)
print(f"半圆面积 A = {A}")
print(f"形心 x̄ = {sp.simplify(x_bar)}")
print(f"形心 ȳ = {sp.simplify(y_bar)}")
# 解析:ȳ = 4R/(3π)
11.7 转动惯量
质量为 的质点绕轴距离 的转动惯量 。连续体的转动惯量:
# 转动惯量案例
import sympy as sp
x, M_total, L_rod = sp.symbols('x M L', positive=True)
# 案例 1:均匀细杆绕中点(质心)转动
# dm = (M/L) dx, r = x, x ∈ [-L/2, L/2]
I_rod_center = sp.integrate((M_total/L_rod) * x**2, (x, -L_rod/2, L_rod/2))
print(f"杆绕中心 I = {sp.simplify(I_rod_center)} = (1/12)ML²")
# 案例 2:均匀圆盘绕中心轴(垂直盘面)
# 极坐标:dm = (M/πR²) · r dr dθ, r² = r²
r, theta, R_disk = sp.symbols('r theta R', positive=True)
sigma = M_total / (sp.pi * R_disk**2)
I_disk = sp.integrate(
sp.integrate(sigma * r**2 * r, (r, 0, R_disk)),
(theta, 0, 2*sp.pi)
)
print(f"圆盘绕中心 I = {sp.simplify(I_disk)} = (1/2)MR²")
# 案例 3:实心球绕直径
# 球坐标系:dm = ρ · r² sin(φ) dr dφ dθ, r² = r²sin²(φ) + ...
# 实际用 r²(到 z 轴距离²) = r²sin²(φ)
phi = sp.Symbol('phi')
rho_density = 3 * M_total / (4 * sp.pi * R_disk**3)
I_sphere = sp.integrate(
sp.integrate(
sp.integrate(
rho_density * (r * sp.sin(phi))**2 * r**2 * sp.sin(phi),
(r, 0, R_disk)
),
(phi, 0, sp.pi)
),
(theta, 0, 2*sp.pi)
)
print(f"实心球绕直径 I = {sp.simplify(I_sphere)} = (2/5)MR²")
11.8 液体静压力
浸入液体中的平板一侧所受压力:
其中 为深度, 为平板在深度 处的宽度, 为液体密度, 为重力加速度。
# 液体压力案例:三角形闸门
import sympy as sp
# 三角形闸门,顶点向下,顶点在水面下 H 处,底边宽 W 在水面
# 在深度 y 处(y 从水面 H 向下),宽度 w(y) = W·y/H
y, W_gate, H_gate, rho, g = sp.symbols('y W H rho g', positive=True)
w_of_y = W_gate * y / H_gate # y ∈ [0, H] 从顶点到底边
F = sp.integrate(rho * g * (H_gate - y) * w_of_y, (y, 0, H_gate))
print(f"三角形闸门压力 F = {sp.simplify(F)}")
# 注:深度从水面算起 = H - y
11.9 引力与电磁场
万有引力的积分形式:连续体对质点的引力需用积分计算。
# 案例:均匀细杆对杆外质点的引力
import sympy as sp
# 杆长 L,质量 M,质点 m 在杆延长线上距杆近端 a 处
# 杆上 dx 处质量 dm = (M/L) dx,到质点距离 (a + x)
# 引力分量 dF = G·m·dm / (a+x)² 沿杆方向
x, L_rod, M_rod, m_p, G_const, a_dist = sp.symbols('x L M m G a', positive=True)
F_grav = sp.integrate(G_const * m_p * (M_rod/L_rod) / (a_dist + x)**2,
(x, 0, L_rod))
print(f"杆对质点引力 = {sp.simplify(F_grav)}")
# 化简:GMm / [a(a+L)]
11.10 应用速查表
| 物理量 | 公式 | 单位 |
|---|---|---|
| 面积 | m² | |
| 体积(截面) | m³ | |
| 体积(圆盘) | m³ | |
| 弧长 | m | |
| 侧面积 | m² | |
| 功 | J | |
| 质心 | m | |
| 转动惯量 | kg·m² | |
| 静压力 | N |
flowchart LR
A[定积分应用] --> B[几何度量]
A --> C[物理建模]
B --> D[面积:∫f-g dx]
B --> E[体积:∫A dx 或 π∫f²dx]
B --> F[弧长:∫√(1+f'²) dx]
B --> G[侧面积:2π∫f·ds]
C --> H[做功:∫F dx]
C --> I[质心:∫xρ dx / ∫ρ dx]
C --> J[转动惯量:∫r² dm]
C --> K[静压力:∫ρgh·w dh]
C --> L[引力:∫Gm·dm/r²]
第 12 章 习题与解答
本章给出 frontmatter 中 10 道习题的详细解答,涵盖 fill-blank、choice、code-fix、open-ended 四类题型。所有证明题均给出完整证明步骤,代码题给出可运行的参考实现。
12.1 填空题解答
习题 ex-calc-di-fb-01:Riemann 可积的极限值与 ____ 及 ξ_i 的取法无关。
解答:分割(或分割方式、分法)。
详细解释:Riemann 可积的严格定义要求:存在实数 ,使得对任意 ,存在 ,对任意分割 ()和任意介点取法 ,都有 。关键在于”任意分割”与”任意介点”二者都无关,这是 Riemann 积分区别于 Darboux 积分表述(只用上下和)的核心。
习题 ex-calc-di-fb-02:Newton-Leibniz 公式中 是 的 ____。
解答:原函数(或一个原函数)。
详细解释:微积分第二基本定理表明,若 在 上连续, 是 的原函数(即 ),则 。连续性是充分条件;对 Riemann 可积但有不连续点的函数,需用更一般的 Lebesgue 微分定理形式。
12.2 选择题解答
习题 ex-calc-di-ch-01:Riemann 可积性论断。
正确答案:B(闭区间上单调函数必 Riemann 可积,即使存在不连续点)。
完整分析:
- A 错:Dirichlet 函数 有界但处处不连续,任何区间上振幅均为 1,不可积。
- B 对:单调函数的间断点至多可数,且在每个区间上振幅 ,故 。
- C 错:Thomae 函数虽在 上可积(间断点为有理数集,可数,测度为零),但陈述”必可积”过强;若函数有第二类间断点(如 在 上无界)则不可积。
- D 错:反例 ,则 可积,但 不可积。
习题 ex-calc-di-ch-02:换元法求 。
正确答案:C(令 )。
完整计算:
当 时 ;当 时 。
展开 ,逐项积分:
习题 ex-calc-di-ch-03: 的收敛性。
正确答案:B(条件收敛)。
完整证明:
-
收敛性(Dirichlet 判别法): 单调递减趋于 , 有界(),故 收敛。
-
非绝对收敛:在区间 上,,故
求和 ,故 发散。
12.3 代码修正题解答
习题 ex-calc-di-cf-01:Simpson 法修正。
修正版:
def simpson(f, a, b, n=10):
"""Simpson 复合公式:要求 n 为偶数"""
if n % 2 != 0:
n += 1
h = (b - a) / n
s = f(a) + f(b)
for i in range(1, n):
# 奇数下标 4 倍,偶数下标 2 倍
coef = 4 if i % 2 == 1 else 2
s += coef * f(a + i * h)
return s * h / 3
import math
print(simpson(math.exp, 0, 1)) # 输出: 1.7182818284590454
错误分析:原代码对所有内点 ()统一用 4 倍权重,违背了 Simpson 复合公式的权重模式 。同时未校验 是否为偶数,Simpson 公式仅在偶数子区间时成立。
习题 ex-calc-di-cf-02:Monte Carlo 修正。
修正版:
import numpy as np
N = 100000
np.random.seed(42) # 固定种子确保可复现
xs = np.random.rand(N)
ys = np.random.rand(N)
f_vals = xs + ys
volume = 1.0 # [0,1]×[0,1] 的面积
estimate = volume * np.mean(f_vals)
print(estimate) # ≈ 1.0000x
错误分析:原代码数学逻辑大体正确(因为 时 Monte Carlo 估计等价于样本均值),但”系统性偏离”通常源于:
- 未固定随机种子,结果不稳定;
- 未显式写出”积分区域体积”乘子,在高维或非单位区域时易错;
- 对期望与积分关系的混淆。
修正版显式保留 volume 项并固定随机种子。
12.4 开放性论述题解答
习题 ex-calc-di-oe-01:用 Riemann 和证明 。
完整证明:
-
取等距分割 :,,则 ,。
-
取介点 (右端点)。
-
Riemann 和:
利用求和公式 :
- 取极限:
- Newton-Leibniz 验证:。
两者一致,故 。
关键说明:本证明用”特殊分割 + 特殊介点”得到极限值 。严格地,因 在 上连续故可积,所以任何分割与介点的极限都等于该值,这是 Riemann 可积性的”与分割无关”公理。
习题 ex-calc-di-oe-02:证明 可积 可积且 。
证明(可积性部分):
设 为 的任一分割,记 ,,类似定义 。
关键不等式:。
证明:对任意 ,
对 取 sup/inf 即得 。
求和:。
由 可积,对任意 存在 使 ,故 ,即 可积。
证明(不等式部分):对任意 ,。由积分的单调性:
即 。
反向反例:。则 在 上 Riemann 可积(),但 不可积(任一区间上振幅为 2)。
习题 ex-calc-di-oe-03:设计 Python 实验验证 。
# 习题 oe-03:数值验证 ∫_0^1 √x dx = 2/3
import numpy as np
from scipy.integrate import quad
import sympy as sp
# (1) Riemann 和数值验证
def riemann_sum(f, a, b, n, mode='right'):
"""Riemann 和:左/右/中点"""
h = (b - a) / n
if mode == 'left':
xs = np.linspace(a, b - h, n)
elif mode == 'right':
xs = np.linspace(a + h, b, n)
else:
xs = np.linspace(a + h/2, b - h/2, n)
return h * np.sum(f(xs))
f = np.sqrt
exact = 2/3
print("Riemann 和收敛性:")
for n in [10, 100, 1000, 10000]:
for mode in ['left', 'right', 'mid']:
val = riemann_sum(f, 0, 1, n, mode)
print(f" n={n:5d}, {mode:5s}: {val:.10f} 误差 {abs(val - exact):.2e}")
print()
# (2) scipy.quad 对照
val_quad, err = quad(f, 0, 1)
print(f"scipy.quad: {val_quad:.12f} 误差 {err:.2e}")
# (3) sympy 符号积分
x = sp.Symbol('x')
val_sym = sp.integrate(sp.sqrt(x), (x, 0, 1))
print(f"sympy 符号: {val_sym} = {float(val_sym):.12f}")
# (4) 误差阶分析:右端点 Riemann 和误差应 ~ O(1/n)
import matplotlib
print("\n误差阶分析:")
prev_err = None
for n in [10, 100, 1000, 10000]:
val = riemann_sum(f, 0, 1, n, 'right')
err_n = abs(val - exact)
if prev_err:
ratio = prev_err / err_n
print(f" n={n:5d}: 误差 {err_n:.4e}, 误差比 {ratio:.2f} (理论 ~10)")
else:
print(f" n={n:5d}: 误差 {err_n:.4e}")
prev_err = err_n
结果分析:由于 在 处导数无界,Riemann 和的收敛速度仅为 而非 。这提示:光滑性影响数值积分的收敛阶。
第 13 章 参考文献
本章节按 ACM Reference Format 列出本篇引用的全部学术文献。完整元数据见 frontmatter 的 references 字段。
13.1 教材类
-
Spivak, M. 2008. Calculus (4th edition). Publish or Perish, Inc. DOI: 10.1007/978-0-387-09469-9.
评注:被誉为”最严格的微积分入门教材”,以 ε-δ 语言贯穿始终,第 13-14 章对积分的处理尤为深刻。
-
Apostol, T. M. 1967. Calculus, Volume 1: One-Variable Calculus with an Introduction to Linear Algebra (2nd edition). John Wiley & Sons.
评注:先于导数引入积分,从面积公理出发构建积分理论,是 MIT 18.01 的标准教材。
-
Apostol, T. M. 1969. Calculus, Volume 2: Multi-Variable Calculus and Linear Algebra with Applications (2nd edition). John Wiley & Sons.
-
Rudin, W. 1976. Principles of Mathematical Analysis (3rd edition). McGraw-Hill Education.
评注:俗称 “Baby Rudin”,第 6 章给出 Riemann-Stieltjes 积分的标准严格处理。
-
Rudin, W. 1987. Real and Complex Analysis (3rd edition). McGraw-Hill Education.
评注:俗称 “Papa Rudin”,第 1-2 章给出 Lebesgue 测度与积分的现代处理。
-
Royden, H. L. and Fitzpatrick, P. M. 2010. Real Analysis (4th edition). Pearson.
-
Folland, G. B. 1999. Real Analysis: Modern Techniques and Their Applications (2nd edition). John Wiley & Sons.
-
Tao, T. 2016. Analysis II (3rd edition). Springer. DOI: 10.1007/978-981-10-1804-6.
评注:Tao 以逐步严格化的风格著称,第 11 章对 Lebesgue 积分的引入极具教学价值。
-
Courant, R. and John, F. 1999. Introduction to Calculus and Analysis II/1. Springer.
-
Munkres, J. R. 1991. Analysis on Manifolds. Westview Press.
评注:第 4 章给出多元 Riemann 积分的严格处理,Fubini 定理证明尤为详尽。
13.2 原始论文类
-
Lebesgue, H. 1902. Intégrale, longueur, aire. Annali di Matematica Pura ed Applicata 7(1): 231-359. DOI: 10.1007/BF02420592.
评注:Lebesgue 测度与积分的奠基性博士论文,将”对 x 轴分割”改为”对 y 轴分割”,突破了 Riemann 理论对不连续函数的限制。
-
Riemann, B. 1868. Über die Darstellbarkeit einer Function durch eine trigonometrische Reihe. Abhandlungen der Königlichen Gesellschaft der Wissenschaften zu Göttingen 13: 87-132.
评注:Riemann 1854 年就职演讲,首次以现代形式严格定义定积分,并提出 Riemann 可积的充要条件(后由 Lebesgue 严格化为”间断点集测度为零”)。
-
Darboux, G. 1875. Mémoire sur la théorie des fonctions discontinues. Annales Scientifiques de l’École Normale Supérieure 4(2): 57-112. DOI: 10.24033/asens.83.
评注:Darboux 引入上下和的简化方法,等价于 Riemann 积分但更便于教学。
-
Henstock, R. 1988. Lectures on the Theory of Integration. World Scientific. DOI: 10.1142/0511.
评注:Henstock-Kurzweill 积分(规范积分)的系统讲述,统一了 Riemann、Lebesgue 与 Newton 积分。
-
Kurzweil, J. 2000. Henstock-Kurzweil Integration: Its Relation to Topological Vector Spaces. World Scientific.
13.3 推荐阅读顺序
初学者路径(本科低年级):
- Spivak → Apostol Vol 1(建立直觉)
- Rudin PMA 第 6 章(严格化)
进阶路径(本科高年级):
- Royden 第 1-4 章(Lebesgue 测度)
- Folland 第 1-2 章(现代观点)
研究路径(研究生):
- Rudin RCA(测度论深入)
- Henstock(非绝对可积积分)
- Tao Analysis II(教学参考)
第 14 章 延伸阅读
定积分理论是现代分析学的基石,与多个数学分支深度交叉。本章给出关联模块的导航与衔接说明。
14.1 重积分与多元积分
关联文档:calculus/重积分.md
将一维 Riemann 积分推广至 上的有界闭集。关键概念:
- Fubini 定理:重积分化为累次积分(本文第 4 章已介绍)
- 变量替换定理:Jacobian 行列式刻画体积伸缩
- Gauss 散度定理:
- Stokes 定理:
这些定理将积分与微分在更高维度统一,是微分几何与电磁学的数学基础。
graph LR
A[一元 Riemann 积分] --> B[多元 Riemann 积分]
B --> C[流形上的积分]
B --> D[Lebesgue 积分]
D --> E[测度论]
D --> F[泛函分析]
C --> G[微分形式]
G --> H[de Rham 上同调]
G --> I[Stokes 定理]
E --> J[概率论基础]
E --> K[调和分析]
14.2 级数与数列
关联文档:math/级数理论.md、math/数列极限.md
定积分与级数通过积分判别法深度关联:
关键主题:
- 正项级数收敛判别法(比较、比值、根值、积分判别)
- 交错级数(Leibniz 判别法)
- 函数级数一致收敛(Weierstrass M-判别法)
- 幂级数与 Taylor 级数
- Fourier 级数与正交函数系
14.3 微分方程
关联文档:math/微分方程.md
定积分是求解微分方程的核心工具:
- 一阶 ODE 的积分因子法: 的通解 ,其中 。
- Picard-Lindelöf 定理:ODE 解的存在唯一性通过积分方程迭代证明。
- Green 函数法:边值问题通过积分核求解。
14.4 概率论
关联文档:math/概率论.md、math/数理统计.md
概率论本质上是测度论的应用:
- 随机变量:可测函数
- 分布函数:
- 期望:
- 方差:
大数定律:样本均值 ,本质上是积分的 Monte Carlo 估计的强收敛。
中心极限定理:,这是本文第 9-10 章 Monte Carlo 积分误差分析的理论基础。
14.5 实分析与测度论
关联文档:math/实分析.md、math/测度论.md
定积分的严格化通往现代分析:
- σ-代数与可测空间:Lebesgue 积分的代数基础
- 测度扩张定理(Carathéodory):从预备测度构造完备测度
- 单调收敛定理与控制收敛定理:积分与极限交换的条件
- Radon-Nikodym 定理:测度间密度的存在性
- Fubini-Tonelli 定理:重积分化为累次积分的严格条件
14.6 数值分析与科学计算
关联文档:cs/数值分析.md、python/scipy.md
本文第 9-10 章覆盖的核心主题在数值分析中深化:
- 正交多项式系(Legendre、Chebyshev、Hermite、Laguerre):不同权函数下的最优求积
- Gauss 求积的一般理论: 点 Gauss 求积的代数精度上限
- 多步法与 Runge-Kutta 法:ODE 求解器中的积分思想
- 谱方法:用正交函数展开求解 PDE
14.7 推荐进阶资源
| 主题 | 推荐资源 | 难度 |
|---|---|---|
| 实分析入门 | Tao, Analysis I & II | ★★★ |
| 测度论 | Folland, Real Analysis | ★★★★ |
| 概率论 | Durrett, Probability: Theory and Examples | ★★★★ |
| 微分方程 | Arnold, Ordinary Differential Equations | ★★★ |
| 微分几何 | Spivak, Calculus on Manifolds | ★★★★ |
| 调和分析 | Stein & Shakarchi, Fourier Analysis | ★★★★ |
| 数值分析 | Trefethen, Approximation Theory and Approximation Practice | ★★★ |
本篇总结:定积分从古希腊穷竭法到 Riemann 严格化再到 Lebesgue 测度,历经两千余年的演化,最终成为现代分析与概率论的统一语言。掌握定积分不仅意味着会计算 ,更意味着理解极限、测度、收敛与近似的深层结构。本篇以 14 章篇幅覆盖了从历史动机、形式化定义、理论推导、数值实现到工程应用的完整链条,40+ Python 代码示例与 10 道 Spivak 风格习题旨在建立”理论-计算-应用”三位一体的能力。继续探索的方向包括重积分、级数、微分方程与概率论,这些主题将在 FANDEX 的后续模块中展开。