跳到正文
格致开物MATHWIKI

埃尔米特插值

埃尔米特插值(Hermite interpolation)在插值节点处同时匹配函数值和指定导数值。与只匹配高度的拉格朗日插值相比,导数条件进一步规定曲线穿过节点时的切线。下文重点讨论两个端点的函数值和一阶导数,它们唯一确定一个次数至多三的多项式。

取区间 [0,1],要求 H(0)=0,H(1)=1,H′(0)=1,H′(1)=0。曲线从零出发时斜率为一,到一处逐渐变平。满足要求的多项式为 H(x)=−x3+x2+x,而不是仅凭两个函数值选择的直线 H=x,因为后者在右端斜率仍为一。

四个端点基函数

对一般端点 x0<x1,令 h=x1−x0、t=(x−x0)/h。定义 h00(t)=2t3−3t2+1,h10(t)=t3−2t2+t,h01(t)=−2t3+3t2,h11(t)=t3−t2. 这四个名字依次对应左端点函数值、左端点导数、右端点函数值和右端点导数,可直接核对它们对四个端点条件的贡献。h00 在左端值为一,其余两个端点值与导数条件都为零;h10 只在左端对 t 的导数为一;另外两者分别对应右端函数值和右端导数。

若端点值为 y0,y1,对原变量 x 的导数为 m0,m1,则 H(x)=h00(t)y0+h10(t)hm0+h01(t)y1+h11(t)hm1. 导数项乘 h 是链式法则要求:dt/dx=1/h,乘上 h 才让对 x 的端点导数恰为 mi。若忽略此因子,在长度不是一的区间上就会给错斜率。[1]

存在唯一性的证明

将 t=0,1 代入四个基函数及其导数,可逐项核对上式满足全部条件,因此解存在。若另有一个次数至多三的多项式 Q 同样满足,差 D=H−Q 在两个端点都满足 D=D′=0,所以 x0,x1 都是至少二重零点。于是 D 能被四次多项式 (x−x0)2(x−x1)2 整除;但 D 次数至多三,只能恒为零。这就证明唯一。

更一般地,n 个不同节点各给函数值和一阶导数,共 2n 个条件,可唯一确定次数至多 2n−1 的插值多项式。唯一性的同一论证使用 n 个二重零点;更高阶导数数据则对应更高重数。这里不是用“方程个数等于未知数个数”直接代替可解性证明。

主例与斜率变式

主例的 h=1,y0=0,y1=1,m0=1,m1=0,所以 H=h10+h01=(x3−2x2+x)+(−2x3+3x2)=−x3+x2+x. 在中点 x=1/2 得 H=5/8。导数为 H′=−3x2+2x+1=(1−x)(3x+1),在区间内非负,符合由零升至一的直观要求。

相同端点零零与一一,两条三次插值曲线;左端斜率一时中点八分之五,左端斜率六时中点四分之五而超过端点最大值
导数数据决定端点之间的形状。匹配相同两个高度不保证曲线没有过冲。

变式。 保持端点值不变,将两端斜率都改为一。代入四基函数得到 H=x,中点为二分之一。若只把左端斜率改为六、右端仍为零,则得到 H=4x3−9x2+6x,中点为 5/4>1。因此即使两个节点值递增,任意给定斜率也不能保证插值单调或始终落在端点值范围内;形状保持插值需要额外限制。

误差中的四次零点因子

若数据来自 f∈C4([x0,x1]),则对每个内部非节点点 x,存在 ξ∈(x0,x1) 使 f(x)−H(x)=f(4)(ξ)4!(x−x0)2(x−x1)2. 证明固定这个 x,令 K=(f(x)−H(x))/[(x−x0)2(x−x1)2],并考察 g(z)=f(z)−H(z)−K(z−x0)2(z−x1)2. 它在两个端点有二重零点,在固定的内部点还有一个零点。反复应用罗尔定理四次,计入端点导数为零提供的重数,可找到 ξ 使 g(4)(ξ)=0。由于三次多项式的四阶导为零,最后一项四阶导为 24K,故 K=f(4)(ξ)/24,得到公式。节点处误差直接为零。

这也给出 |f−H|≤‖f(4)‖∞h4/384,因为区间内 |(x−x0)(x−x1)|≤h2/4。没有四阶光滑性或准确端点导数时,这个余项结论的条件就不满足。

可运行的双端点实现

下列函数仅计算已给四个端点条件对应的三次片段。输入有限实数,要求端点递增;不改写任何数据。数学公式也可用于区间外求值,但上述区间内误差界不因此变成外推保证。

Python 3
from math import isfinite

def hermite_segment(x0, x1, y0, y1, m0, m1, x):
    x0, x1, y0, y1, m0, m1, x = map(float, (x0, x1, y0, y1, m0, m1, x))
    if not all(isfinite(z) for z in (x0, x1, y0, y1, m0, m1, x)) or x1 <= x0:
        raise ValueError("finite data and increasing endpoints required")
    h = x1 - x0
    t = (x - x0) / h
    h00 = 2*t**3 - 3*t**2 + 1
    h10 = t**3 - 2*t**2 + t
    h01 = -2*t**3 + 3*t**2
    h11 = t**3 - t**2
    return h00*y0 + h10*h*m0 + h01*y1 + h11*h*m1

assert hermite_segment(0, 1, 0, 1, 1, 0, 0.5) == 5/8
assert hermite_segment(0, 1, 0, 1, 1, 1, 0.5) == 0.5
assert hermite_segment(0, 1, 0, 1, 6, 0, 0.5) == 5/4
assert hermite_segment(2, 4, 3, 7, 2, 2, 3) == 5
assert hermite_segment(0, 1, 0, 1, 1, 0, 1) == 1
print(hermite_segment(0, 1, 0, 1, 1, 0, 0.5))

每次求值只进行固定数量的多项式运算,时间与额外空间均为 O(1)。程序的正确性直接由基函数满足四个端点条件和唯一性定理保证;非单位长度的线性变式检验了导数前面的区间长度因子。

参考文献

  1. ↑ SciPy开发团队:CubicHermiteSpline,分段三次Hermite插值、数据值与一阶导数条件及严格递增节点。访问日期:2026-10-22。