牛顿插值法是一种重要的插值方法,与拉格朗日插值法在同阶时产生的多项式在化简以后是一样的,余项也是一样的,因此两者只是写法形式不同而已。在针对变化的数据时,其各自独特的写法形式给其适合的应用场景带来了区别。牛顿插值法适用于被插的点不断增多,而且可以很好的复用以前的计算结果。

牛顿(Newton)插值

Newton 公式中有一些差商、差分的概念及性质我们可以先了解下。

插商

定义 

设有函数f (x), x0 , x1, x2 ,...,为一系列互不相等的点,称



艾尔米特分段三次插值python_matlab 函数拟合 线性插值

为f (x)关于点 xi , xj 一阶差商(也称均差),记为  f[xi ,xj ]   ,即



艾尔米特分段三次插值python_matlab 插值_02

称一阶差商的差商



艾尔米特分段三次插值python_matlab 函数拟合 线性插值_03

为 f (x)关于点xi , xj ,xk 的二阶差商,记为 f[xi ,xj , xk]  。一般地,称



艾尔米特分段三次插值python_matlab 函数拟合 线性插值_04

为 f (x)关于点 x0 ,x1,...,xk 的k 阶差商,记为



艾尔米特分段三次插值python_艾尔米特分段三次插值python_05

容易证明,差商具有下述性质:



艾尔米特分段三次插值python_matlab 插值_06

Newton 插值公式 

线性插值公式可表成



艾尔米特分段三次插值python_matlab 插值_07

称为一次 Newton 插值多项式。一般地,由各阶差商的定义,依次可得



艾尔米特分段三次插值python_hermite插值_08

将以上各式分别乘以



艾尔米特分段三次插值python_matlab 插值_09

然后相加并消去两边相等的部分,即得



艾尔米特分段三次插值python_matlab 分段函数_10



艾尔米特分段三次插值python_matlab 插值_11

显然,Nn(x) 是至多n次的多项式,且满足插值条件,因而它是 f (x)的n次插值多项式。这种形式的插值多项式称为 Newton 插值多项式。Rn(x) 称为 Newton 插值余项。

Newton 插值的优点是:每增加一个节点,插值多项式只增加一项,即



艾尔米特分段三次插值python_matlab 分段函数_12

因而便于递推运算。而且Newton 插值的计算量小于Lagrange 插值。

由插值多项式的唯一性可知,Newton 插值余项与Lagrange 余项也是相等的,即



艾尔米特分段三次插值python_hermite插值_13

由此可得差商与导数的关系



艾尔米特分段三次插值python_matlab 插值_14

差分

当节点等距时,即相邻两个节点之差(称为步长)为常数,Newton 插值公式的形式会更简单。此时关于节点间函数的平均变化率(差商)可用函数值之差(差分)来表示。 

定义 

设有等距节点 ( 0,1, , ) xk = x0 + kh (k = 0,1,..., n) ,步长 h 为常数, f k  = f( xk) 。称相邻两个节点 xk,xk+1 处的函数值的增量  f k +1 − f( k  = 0,1,..., n−1)为函数 f (x) 在 点 k x 处以h 为步长的一阶差分,记为  Δfk ,即



艾尔米特分段三次插值python_hermite插值_15

称为 f (x) 在 xk 处以 h 为步长的中心差分。一般地, m 阶向后差分与 m 阶中心差分公式为



艾尔米特分段三次插值python_hermite插值_15

艾尔米特分段三次插值python_hermite插值_17

差分具有以下性质: 

(i)各阶差分均可表成函数值的线性组合,例如



艾尔米特分段三次插值python_matlab 函数拟合 线性插值_18

(ii)各种差分之间可以互化。向后差分与中心差分化成向前差分的公式如下:



艾尔米特分段三次插值python_matlab 插值_19

 等距节点插值公式 

如果插值节点是等距的,则插值公式可用差分表示。设已知节点



艾尔米特分段三次插值python_matlab 插值_20

则有



艾尔米特分段三次插值python_matlab 函数拟合 线性插值_21

上式称为Newton 向前插值公式。

牛顿插值实例

已知节点 0, 2, 3, 5 对应的函数值为 1, 3, 2, 5,构造三次Newton 插值多项式,当 x = 2.5 时,计算 Newton 多项式插值结果。

解:

由前面计算的差商值,我们很容易写出三次 Newton 插值多项式如下:



艾尔米特分段三次插值python_matlab 插值_22

当 x = 2.5 时,Newton 多项式插值结果为:



艾尔米特分段三次插值python_hermite插值_23

艾尔米特分段三次插值python_matlab 插值_24

艾尔米特分段三次插值python_matlab 分段函数_25

输出结果:



艾尔米特分段三次插值python_艾尔米特分段三次插值python_26

下面简单给大家介绍一些其他插值算法



艾尔米特分段三次插值python_matlab 函数拟合 线性插值_27

分段线性插值

插值多项式的振荡

用Lagrange 插值多项式Ln (x) 近似f(x)(a ≤ x ≤ b),虽然随着节点个数的增加,Ln 的次数n 变大,多数情况下误差| Rn (x) |会变小。

但是n 增大时,Ln (x) 的光滑性变坏,有时会出现很大的振荡。理论上,当n → ∞ ,在[a,b]内并不能保证Ln (x)处处收敛于 f (x)。Runge 给出了一个有名的例子



艾尔米特分段三次插值python_matlab 插值_28

对于较大的| x |,随着n 的增大,Ln (x) 振荡越来越大,事实上可以证明,仅当| x |≤ 3.63 时,才有



艾尔米特分段三次插值python_matlab 分段函数_29

而在此区间外,Ln (x)是发散的。

高次插值多项式的这些缺陷,促使人们转而寻求简单的低次多项式插值。

分段线性插值函数

简单地说,将每两个相邻的节点用直线连起来,如此形成的一条折线就是分段线性插值函数,记作

艾尔米特分段三次插值python_matlab 插值_30

,它满足In (xi ) = yi ,且

艾尔米特分段三次插值python_matlab 插值_30

 在每个小区间[xi , xi+1 ]上是线性函数(i = 0,1,...,n) 。

艾尔米特分段三次插值python_matlab 插值_30

可表示为

艾尔米特分段三次插值python_hermite插值_33


艾尔米特分段三次插值python_matlab 插值_30

计算x 点的插值时,只用到x 左右的两个节点,计算量与节点个数n 无关。但n 越大,分段越多,插值误差越小。实际上用函数表作插值计算时,分段线性插值就足够了,如数学、物理中用的特殊函数表,数理统计中用的概率分布表等。

 用Matlab 实现分段线性插值

用Matlab 实现分段线性插值不需要编制函数程序,Matlab 中有现成的一维插值函数interp1。

y=interp1(x0,y0,x,'method')

method 指定插值的方法,默认为线性插值。其值可为:

'nearest' 最近项插值

 'linear' 线性插值

'spline' 逐段3 次样条插值 

'cubic' 保凹凸性3 次插值

所有的插值方法要求x0 是单调的。

当 x0 为等距时可以用快速插值法,使用快速插值法的格式为'*nearest'、'*linear'、 '*spline'、'*cubic'。

 埃尔米特(Hermite)插值 

Hermite 插值多项式如果对插值函数,不仅要求它在节点处与函数同值,而且要求它与函数有相同的一阶、二阶甚至更高阶的导数值,这就是Hermite 插值问题。

设已知函数y = f (x) 在n +1个互异节点x0 ,x1 ,..., xi上的函数值yi = f (xi ),(i = 0,1,L,n) 和导数值 


艾尔米特分段三次插值python_matlab 分段函数_35

要求一个至多2n +1次的多项式H(x),使得


艾尔米特分段三次插值python_matlab 插值_36

满足上述条件的多项式H(x)称为Hermite 插值多项式。

Hermite 插值多项式为


艾尔米特分段三次插值python_hermite插值_37

用Matlab 实现Hermite 插值

Matlab 中没有现成的Hermite 插值函数,必须编写一个M 文件实现插值。

设n 个节点的数据以数组x0(已知点的横坐标),y0 (函数值),y1(导数值) 输入(注意Matlat 的数组下标从1 开始),m 个插值点以数组x 输入,输出数组y 为m 个插值。编写一个名为hermite.m 的M 文件:

function y=hermite(x0,y0,y1,x); n=length(x0);m=length(x);
for k=1:m
yy=0.0; 
for i=1:n
h=1.0; 
a=0.0; 
for j=1:n
if j~=i
h=h*((x(k)-x0(j))/(x0(i)-x0(j)))^2; 
a=1/(x0(i)-x0(j))+a;
end 
end
yy=yy+h*((x0(i)-x(k))*(2*a*y0(i)-y1(i))+y0(i)); end
y(k)=yy;
end