跳到正文
格致开物MATHWIKI

龙贝格积分

龙贝格积分(Romberg integration)把逐次减半步长的复合梯形公式组织成一个三角表,再用理查森外推逐层消去主导误差项。它利用光滑函数的梯形误差通常按偶次步长展开这一结构,而不是仅把更多采样值作平均。

以 I=∫01x4dx=1/5 为教学算例。梯形网格从一个区间细化为两个、四个区间,近似值依次为 1/2,9/32,113/512。仅靠细化还未精确;对这三项作两层外推,会得到恰好 1/5。

梯形网格复用旧节点

令 hk=(b−a)/2k,以 Tk 记步长 hk 的复合梯形近似。第一项为 T0=(b−a)(f(a)+f(b))/2。细化时旧节点权重减半,只需补上原各小区间的中点,因此 Tk=12Tk−1+hk∑i=12k−1f(a+(2i−1)hk). 主例有 T0=1/2,然后 T1=14+12(12)4=932, T2=12932+14[(14)4+(34)4]=113512. 每次只计算新出现的奇数网格点,不必重新评价全部旧节点。[1]

消去偶次误差的递推证明

在足够光滑的条件下,梯形误差有展开 T(h)=I+c2h2+c4h4+⋯. 例如要按此展开论证到指定有限阶,需相应高阶导数在整个闭区间存在并连续,不能只检查节点处函数值有限。比较步长 h 与 2h,两项的主导误差分别为 c2h2 和 4c2h2,所以 4T(h)−T(2h)3=I+O(h4). 系数四来自二次误差在步长加倍后变为四倍;分母三则使常数项仍保持为 I。

定义 Rk,0=Tk。第 j 层消去 h2j 项,递推为 Rk,j=4jRk,j−1−Rk−1,j−14j−1,1≤j≤k. 其正确性可作归纳:若上一层在步长 hk 下为 I+Chk2j+O(hk2j+2),同层上一行的步长为 2hk,主项系数变为 4jC。按上式相减便消去该项,常数项又除以 4j−1 保持不变,余项为 O(hk2j+2)。因此每加一列,在光滑展开有效的前提下提高两阶,而非由某一次结果恰好很准推断。

主例的完整三角表

第一列是梯形值,其余列依次计算为 R1,1=4(9/32)−1/23=524,R2,1=4(113/512)−9/323=77384, R2,2=16(77/384)−5/2415=15.

三角表第一列二分之一、三十二分之九、五百一十二分之一百一十三,第二列二十四分之五、三百八十四分之七十七,末列五分之一
每个新条目使用左侧本行与上一行的同列条目;第二次外推的系数是十六。

对这个四次多项式,梯形误差实际上恰为 T(h)−I=h2/3−h4/30。第一列之后只有这两个误差幂,两层外推把它们都消掉,因此精确。这一特殊精确性不表示一般函数也会在四个小区间后得到精确积分。

变式。 将被积函数改成 x2,则 T0=1/2,T1=3/8,一次外推就得到 (4⋅3/8−1/2)/3=1/3。因为此时梯形误差只有 h2 项,一层已经足够。

固定层数的Python实现

函数返回全部三角表,输入层数 L≥1 表示行编号零到 L−1,最细网格有 2L−1 个小区间。它不进行自适应停止,也不改写用户数据;每个采样值必须有限。区间端点允许相同,此时直接返回零积分表,不调用被积函数。

Python 3
from math import fsum, isfinite

def romberg_table(function, a, b, levels):
    a, b = float(a), float(b)
    if not isfinite(a) or not isfinite(b) or b < a:
        raise ValueError("finite ordered endpoints required")
    if type(levels) is not int or levels < 1:
        raise ValueError("levels must be a positive integer")
    if a == b:
        return [[0.0]*(k+1) for k in range(levels)]
    def sample(x):
        value = float(function(x))
        if not isfinite(value):
            raise ValueError("nonfinite integrand sample")
        return value
    table = [[(b-a)*(sample(a)+sample(b))/2]]
    for k in range(1, levels):
        h = (b-a) / 2**k
        new_sum = fsum(sample(a+(2*i-1)*h) for i in range(1, 2**(k-1)+1))
        row = [table[k-1][0]/2 + h*new_sum]
        for j in range(1, k+1):
            factor = 4**j
            row.append((factor*row[j-1]-table[k-1][j-1])/(factor-1))
        table.append(row)
    return table

table = romberg_table(lambda x: x**4, 0, 1, 3)
assert table[0][0] == 1/2
assert table[1][0] == 9/32
assert table[2][0] == 113/512
assert abs(table[2][2] - 1/5) < 1e-14
assert abs(romberg_table(lambda x: x*x, 0, 1, 2)[1][1] - 1/3) < 1e-14
assert romberg_table(lambda x: 1/0, 2, 2, 2) == [[0.0], [0.0, 0.0]]
cusp = romberg_table(lambda x: abs(x-0.5), 0, 1, 2)
assert cusp[1][0] == 1/4 and abs(cusp[1][1] - 1/6) < 1e-14
print(table)

到第 L−1 行共需 2L−1+1 次函数评价,旧节点不重算;外推表有 O(L2) 个条目,因此时间为 O(2L+L2),保存完整表占 O(L2) 空间。若只保留前后两行可减少表存储,但本实现保留全部步骤便于复核。

光滑性失效与停止误差

取 f(x)=|x−1/2|,真积分为 1/4。两小区间的梯形公式已恰好精确,但粗网格 T0=1/2,所以外推值却为 (4⋅1/4−1/2)/3=1/6,反而变差。原因是中点处有尖角,跨越不同网格的误差不满足所用的固定偶次展开。

相邻对角条目的差常用作经验误差指标,却不是无条件的严格误差界。端点奇异、强振荡、舍入误差或函数评价误差都可能破坏外推改进;必要时应先分割奇点、作变量替换,或选择适合该结构的求积公式。

参考文献

  1. ↑ NIST Digital Library of Mathematical Functions:§3.5 Quadrature,复合梯形公式、Euler—Maclaurin展开与Romberg积分。访问日期:2026-10-22。