数值分析 |多项式插值、牛顿插值、样条插值

文章目录

  • 参考资料
  • 1. 基本概念
    • 1.1 函数逼近-插值-拟合的区别
    • 1.2 插值定义
  • 2. 多项式插值
    • 2.1 线性插值
      • 2.1.1 定义
      • 2.1.2 例题
    • 2.2 抛物线插值(二次插值)
    • 2.3 插值多项式的存在唯一性
    • 2.4 Lagrange插值法
      • 2.4.1 原理
      • 2.4.2 C++实现
  • 3. 牛顿差商公式、样条插值*
    • 3.1 牛顿差商公式
    • 3.2 样条插值

参考资料

  • 《统计计算》
  • 插值方法原理详解
  • 函数逼近&&插值、函数逼近&曲线拟合的区别
  • 线性插值、抛物插值、Lagrange插值

1. 基本概念

1.1 函数逼近-插值-拟合的区别

  • 函数逼近
    已知原函数的情况下,找一个简单函数逼近于原函数,使得在定义域上的误差达到最大值的点的误差达到最小。

  • 插值
    插值就是根据已知数据点(条件),来预测未知数据点值的方法。用一个多项式来近似代替数据列表的函数,并要求函数式通过给定的数据点。——针对于离散的点,并求出函数表达式过数据点。

  • 拟合
    原函数未知,给定原函数的若干点,在某个简单函数空间找出使得总误差(根据不同定义有不同的误差距离的衡量,一般是均方误差)最小的那个简单函数,这即意味着尽可能地使拟合函数靠近采样点,而不须要严格的通过这些采样点,一般为了提高拟合精度,要求尽可能多地采样点。
    l o s s = ∑ n i = 1 e i 2 = ∑ n i = 1 ( z i − f ( x i ) ) 2 loss=\sum^{i=1}_{n}e_i^2=\sum^{i=1}_{n}(z_i-f(x_i))^2 loss=ni=1ei2=ni=1(zif(xi))2
    上述就是常见地均方误差构造形式,其中函数 f ( x ) f(x) f(x)称为拟合函数。

1.2 插值定义

一般地,设已知函数 h ( x ) h(x) h(x) 在点 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,,xn 上的值 z 1 , z 2 , … , z n ( z i = h ( x i ) ) z_1, z_2, \ldots, z_n\left(z_i=h\left(x_i\right)\right) z1,z2,,zn(zi=h(xi)) ,在假定 h ( x ) h(x) h(x) 具有一定 光滑度的条件下可以用函数 f ( x ) f(x) f(x) 近似计算 h ( x ) h(x) h(x) 在自变量 x x x 处的值。

h ( x ) h(x) h(x) 为被插值函数, x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,,xn 叫做节点, f ( x ) f(x) f(x) 叫做插值函数。

如果我们只能获得 h ( x ) h(x) h(x) 在有限个点上的值,可以用插值方法近似计算 h ( x ) h(x) h(x) 在其它自变量处的值。如果函数 h ( x ) h(x) h(x) 每计算一个函数值到所需 精度都要花费很长时间,可以预先在一些自变量处计算函数值并保存好,然后需要用到 h ( x ) h(x) h(x) 的值时用插值 法近似计算整个定义域上的函数值。如果 h ( x ) h(x) h(x) 的计算精度要求不高,也可以预先计算并保存部分自变量处 的函数值,然后用插值来近似函数值。插值得到的表达式可以用于积分、微分计算。

2. 多项式插值

一般使用多项式或分段多项式作插值函数,即为多项式插值。

2.1 线性插值

2.1.1 定义

用连接两点的线段作为插值公式的方法叫做线性插值。一般地,设已知 ( x i , z i ) , i = 1 , … , n \left(x_i, z_i\right), i=1, \ldots, n (xi,zi),i=1,,n, z i = h ( x i ) z_i=h\left(x_i\right) zi=h(xi) 。对 x ∈ [ x i − 1 , x i ] x \in\left[x_{i-1}, x_i\right] x[xi1,xi], 令
h ( x ) ≈ f ( x ) = z i − 1 + z i − z i − 1 x i − x i − 1 ( x − x i − 1 ) (1) \tag{1} h(x) \approx f(x)=z_{i-1}+\frac{z_i-z_{i-1}}{x_i-x_{i-1}}\left(x-x_{i-1}\right) h(x)f(x)=zi1+xixi1zizi1(xxi1)(1)
(这就是直线方程的斜截式)。如果记 α = x − x i − 1 x i − x i − 1 \alpha=\frac{x-x_{i-1}}{x_i-x_{i-1}} α=xixi1xxi1 ,则
f ( x ) = ( 1 − α ) z i − 1 + α z i . (2) \tag{2} f(x)=(1-\alpha) z_{i-1}+\alpha z_i . f(x)=(1α)zi1+αzi.(2)
h ( x ) h(x) h(x) 本身在 [ x i − 1 , x i ] \left[x_{i-1}, x_i\right] [xi1,xi] 就是一次多项式时插值是精确的。

除了用斜截式表示外,还可以用对称式表示:
h ( x ) ≈ f ( x ) = x − x i − 1 x i − x i − 1 z i + x − x i x i − 1 − x i z i − 1 (3) \tag{3} h(x) \approx f(x)=\frac{x-x_{i-1}}{x_{i}-x_{i-1}}z_i+\frac{x-x_{i}}{x_{i-1}-x_{i}}z_{i-1} h(x)f(x)=xixi1xxi1zi+xi1xixxizi1(3)
l i ( x ) = x − x i − 1 x i − x i − 1 l_i(x)=\frac{x-x_{i-1}}{x_{i}-x_{i-1}} li(x)=xixi1xxi1 l i − 1 ( x ) = x − x i x i − 1 − x i l_{i-1}(x)=\frac{x-x_{i}}{x_{i-1}-x_{i}} li1(x)=xi1xixxi,则有
f ( x ) = l i ( x ) z i + l i − 1 ( x ) z i − 1 (4) \tag{4} f(x)=l_i(x)z_i+l_{i-1}(x)z_{i-1} f(x)=li(x)zi+li1(x)zi1(4)
公式(4)意味着满足插值条件 f ( x i ) = z i , f ( x i − 1 ) = z i − 1 f(x_i)=z_i,f(x_{i-1})=z_{i-1} f(xi)=zi,f(xi1)=zi1的线性插值多项式 f ( x ) f(x) f(x),可用两个插值基函数 l i ( x ) , l i − 1 ( x ) l_i(x),l_{i-1}(x) li(x),li1(x)进行线性组合构造。

2.1.2 例题

下表是 F ( 1 , n ) F(1, n) F(1,n) 分布的 0.95 0.95 0.95 分位数的部分值:

n n n ⋯ \cdots 20 ⋯ \cdots 29 30 40 60 120 ∞ \infty
h ( n ) h(n) h(n) ⋯ \cdots 4.35 4.35 4.35 ⋯ \cdots 4.18 4.18 4.18 4.17 4.17 4.17 4.08 4.08 4.08 4.00 4.00 4.00 3.92 3.92 3.92 3.84 3.84 3.84

设关于函数 h ( n ) h(n) h(n) 我们只有上述知识,但是还知道 h ( n ) h(n) h(n) 具有一定光滑性。这里 h ( 30 ) = 4.17 , h ( 40 ) = 4.08 h(30)=4.17, h(40)=4.08 h(30)=4.17,h(40)=4.08 , 为了计算 h ( 32 ) h(32) h(32) ,只要把 ( 30 , h ( 30 ) ) (30, h(30)) (30,h(30)) ( 40 , h ( 40 ) ) (40, h(40)) (40,h(40)) 这两个点用线段连接,在 ( 30 , 40 ) (30,40) (30,40) 之间用连接的线段作 为 h ( x ) h(x) h(x) 的近似值,通过公式(1)就可以计算
h ( 32 ) = h ( 30 ) + h ( 40 ) − h ( 30 ) 40 − 30 ( 32 − 30 ) ≈ 4.15 h(32)=h(30)+\frac{h(40)-h(30)}{40-30}(32-30) \approx 4.15 h(32)=h(30)+4030h(40)h(30)(3230)4.15

2.2 抛物线插值(二次插值)

当已知三个点的函数值时可以找到穿过这三个点的抛物线,抛物插值就是通过3个采样点构造一个二次多项式 f ( x ) f(x) f(x)作为 h ( x ) h(x) h(x) 的近似值。设三个点分别为 ( x 0 , z 0 ) , ( x 1 , z 1 ) , ( x 2 , z 2 ) \left(x_{0}, z_{0}\right),\left(x_1, z_1\right),\left(x_2, z_2\right) (x0,z0),(x1,z1),(x2,z2)

由于 f ( x ) f(x) f(x)经过三个已知点,用待定系数法可以确定出二次多项式 f ( x ) = a 0 + a 1 x + a 2 x 2 f(x)=a_0+a_1x+a_2x^2 f(x)=a0+a1x+a2x2 的各个系数。

这里为避免解方程组,使用基函数线性组合的构造方法来求二次多项式 f ( x ) f(x) f(x) 。由线性插值的结论推广可知,该二次多项式 f ( x ) f(x) f(x) 可用 3 个插值基函数 l 0 ( x ) , l 1 ( x ) , l 2 ( x ) l_0(x), l_1(x), l_2(x) l0(x),l1(x),l2(x) 进行线性组合构造。即:
f ( x ) = l 0 ( x ) ⋅ z 0 + l 1 ( x ) ⋅ z 1 + l 2 ( x ) ⋅ z 2 (5) \tag{5} f(x)=l_0(x) \cdot z_0+l_1(x) \cdot z_1+l_2(x) \cdot z_2 f(x)=l0(x)z0+l1(x)z1+l2(x)z2(5)
3 个插值基函数在插值节点 x 0 , x 1 x_0, x_1 x0,x1 x 2 x_2 x2 处应该分别满足:
l 0 ( x 0 ) = 1 l 0 ( x 1 ) = 0 l 0 ( x 2 ) = 0 l 1 ( x 0 ) = 0 l 1 ( x 1 ) = 1 l 1 ( x 2 ) = 0 l 2 ( x 0 ) = 0 l 2 ( x 1 ) = 0 l 2 ( x 2 ) = 1 (6) \tag{6} \begin{array}{lll} l_0\left(x_0\right)=1 & l_0\left(x_1\right)=0 & l_0\left(x_2\right)=0 \\ l_1\left(x_0\right)=0 & l_1\left(x_1\right)=1 & l_1\left(x_2\right)=0 \\ l_2\left(x_0\right)=0 & l_2\left(x_1\right)=0 & l_2\left(x_2\right)=1 \end{array} l0(x0)=1l1(x0)=0l2(x0)=0l0(x1)=0l1(x1)=1l2(x1)=0l0(x2)=0l1(x2)=0l2(x2)=1(6)
即只要确定出 3 个插值基函数即可。

根据 l 0 ( x 1 ) = l 0 ( x 2 ) = 0 l_0\left(x_1\right)=l_0\left(x_2\right)=0 l0(x1)=l0(x2)=0 ,可假设 l 0 ( x ) = C ( x − x 1 ) ( x − x 2 ) l_0(x)=\mathrm{C}\left(x-x_1\right)\left(x-x_2\right) l0(x)=C(xx1)(xx2) ; 将 l 0 ( x 0 ) = 1 l_0\left(x_0\right)=1 l0(x0)=1 代入,得:
C ( x 0 − x 1 ) ( x 0 − x 2 ) = 1 \mathrm{C}\left(x_0-x_1\right)\left(x_0-x_2\right)=1 C(x0x1)(x0x2)=1

C = 1 ( x 0 − x 1 ) ( x 0 − x 2 ) \mathrm{C}=\frac{1}{\left(x_0-x_1\right)\left(x_0-x_2\right)} C=(x0x1)(x0x2)1
所以
l 0 ( x ) = ( x − x 1 ) ( x − x 2 ) ( x 0 − x 1 ) ( x 0 − x 2 ) (7) \tag{7} l_0(x)=\frac{\left(x-x_1\right)\left(x-x_2\right)}{\left(x_0-x_1\right)\left(x_0-x_2\right)} l0(x)=(x0x1)(x0x2)(xx1)(xx2)(7)
同理
l 1 ( x ) = ( x − x 0 ) ( x − x 2 ) ( x 1 − x 0 ) ( x 1 − x 2 ) (8) \tag{8} l_1(x)=\frac{\left(x-x_0\right)\left(x-x_2\right)}{\left(x_1-x_0\right)\left(x_1-x_2\right)} l1(x)=(x1x0)(x1x2)(xx0)(xx2)(8)
l 2 ( x ) = ( x − x 0 ) ( x − x 1 ) ( x 2 − x 0 ) ( x 2 − x 1 ) (9) \tag{9} l_2(x)=\frac{\left(x-x_0\right)\left(x-x_1\right)}{\left(x_2-x_0\right)\left(x_2-x_1\right)} l2(x)=(x2x0)(x2x1)(xx0)(xx1)(9)
这样,由 (6) 、(7)、(8) 和 (9) 式就构成了抛物插值公式。即:
f ( x ) = ( x − x 1 ) ( x − x 2 ) ( x 0 − x 1 ) ( x 0 − x 2 ) ⋅ z 0 + ( x − x 0 ) ( x − x 2 ) ( x 1 − x 0 ) ( x 1 − x 2 ) ⋅ z 1 + ( x − x 0 ) ( x − x 1 ) ( x 2 − x 0 ) ( x 2 − x 1 ) ⋅ z 2 (10) \tag{10} f(x)=\frac{\left(x-x_1\right)\left(x-x_2\right)}{\left(x_0-x_1\right)\left(x_0-x_2\right)} \cdot z_0+\frac{\left(x-x_0\right)\left(x-x_2\right)}{\left(x_1-x_0\right)\left(x_1-x_2\right)} \cdot z_1+\frac{\left(x-x_0\right)\left(x-x_1\right)}{\left(x_2-x_0\right)\left(x_2-x_1\right)} \cdot z_2 f(x)=(x0x1)(x0x2)(xx1)(xx2)z0+(x1x0)(x1x2)(xx0)(xx2)z1+(x2x0)(x2x1)(xx0)(xx1)z2(10)

2.3 插值多项式的存在唯一性

定理:
设有采样点 { ( x i , z i ) , i = 0 , 1 , … , n − 1 } \left\{\left(x_i, z_i\right), i=0,1, \ldots, n-1\right\} {(xi,zi),i=0,1,,n1} 互不相同,则存在唯一的不超过 n − 1 n-1 n1 阶 的多项式 P n − 1 ( x ) P_{n-1}(x) Pn1(x) 使得
P n − 1 ( x i ) = z i , i = 0 , 1 , … , n − 1. P_{n-1}\left(x_i\right)=z_i, i=0,1, \ldots, n-1 . Pn1(xi)=zi,i=0,1,,n1.

证明:

P n − 1 ( x ) = a 0 + a 1 x + … + a n − 1 x n − 1 P_{n-1}(x)=a_0+a_1 x+\ldots+a_{n-1} x^{n-1} Pn1(x)=a0+a1x++an1xn1 为多项式, 其中 a 0 , a 1 , … , a n − 1 a_0, a_1, \ldots, a_{n-1} a0,a1,,an1 为待定常数。为使 P n − 1 ( x i ) = z i , i = 0 , 1 , … , n − 1 P_{n-1}\left(x_i\right)=z_i, i=0,1, \ldots, n-1 Pn1(xi)=zi,i=0,1,,n1 ,应有
( 1 x 0 x 0 2 ⋯ x 0 n − 1 1 x 1 x 1 2 ⋯ x 1 n − 1 ⋮ ⋮ ⋮ ⋱ ⋮ 1 x n − 1 x n − 1 2 ⋯ x n − 1 n − 1 ) ( a 0 a 1 a 2 ⋮ a n − 1 ) = ( z 0 z 1 ⋮ z n − 1 ) (11) \tag{11} \left(\begin{array}{ccccc} 1 & x_0 & x_0^2 & \cdots & x_0^{n-1} \\ 1 & x_1 & x_1^2 & \cdots & x_1^{n-1} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_{n-1} & x_{n-1}^2 & \cdots & x_{n-1}^{n-1} \end{array}\right)\left(\begin{array}{c} a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_{n-1} \end{array}\right)=\left(\begin{array}{c} z_0 \\ z_1 \\ \vdots \\ z_{n-1} \end{array}\right) 111x0x1xn1x02x12xn12x0n1x1n1xn1n1 a0a1a2an1 = z0z1zn1 (11)
注意到此方程组的系数矩阵行列式为Vandermonde行列式,行列式值为
∏ 0 ≤ i < j ≤ n − 1 ( x j − x i ) ≠ 0 \prod_{0 \leq i0i<jn1(xjxi)=0
所以方程组存在唯一解, 即存在唯一的次数不超过 n − 1 n-1 n1 的多项式 P n − 1 ( x ) P_{n-1}(x) Pn1(x) 使 P n − 1 ( x ) P_{n-1}(x) Pn1(x) 通过 ( x i , z i ) , i = 0 , 1 , … , n − 1 \left(x_i, z_i\right), i=0,1, \ldots, n-1 (xi,zi),i=0,1,,n1 n n n 个点。

由上述证明可见,求插值多项式的方法之一是解线性方程组(11)。

2.4 Lagrange插值法

2.4.1 原理

根据(2.3)小节,由 n n n个采样点可以惟一地构造出一个次数不高于 n − 1 n-1 n1的插值多项式 P n − 1 ( x ) P_{n-1}(x) Pn1(x)

在构造该插值多项式时,同样采用基函数线性组合的构造方法,可认为该插值多项式 P n − 1 ( x ) P_{n-1}(x) Pn1(x) 由n个插值基函数线性组合而成,其组合系数就是对应插值节点上的函数值 z i ( i = 0 , 1 , 2 , ⋯   , n − 1 ) z_i ( i = 0 , 1 , 2 , ⋯   , n-1 ) zi(i=0,1,2,,n1)

P n − 1 ( x ) = ∑ i = 0 n − 1 l i ( x ) z i (12) \tag{12} P_{n-1}(x)=\sum_{i=0}^{n-1}{l_i(x)z_i} Pn1(x)=i=0n1li(x)zi(12)

在插值节点 x i x_i xi上,该多项式满足插值条件:
P n − 1 ( x i ) = z i ( i = 0 , 1 , 2 , ⋯   , n − 1 ) P_{n-1}(x_i)=z_i\\ ( i = 0 , 1 , 2 , ⋯   , n-1 ) Pn1(xi)=zi(i=0,1,2,,n1)

因此,为了使插值条件成立,这 n n n 个插值基函数 l i ( x ) ( i = 0 , 1 , 2 , ⋯   , k , ⋯   , n − 1 ) l_{i}(x)(i=0,1,2, \cdots, k, \cdots, n-1) li(x)(i=0,1,2,,k,,n1) n n n 个插值节点上必须分别满足:
l i ( x k ) = { 0 , k ≠ i 1 , k = i l_{i}\left(x_{k}\right)= \begin{cases}0, & k \neq i \\ 1, & k=i\end{cases} li(xk)={0,1,k=ik=i
因此,插值基函数 l i ( x ) l_{i}(x) li(x) 有一个非零点 x i x_{i} xi n − 1 n-1 n1 个零点 x 0 , x 1 , ⋯   , x i − 1 , x i + 1 , ⋯   , x n − 1 x_0, x_1, \cdots, x_{i-1}, x_{i+1}, \cdots, x_{n-1} x0,x1,,xi1,xi+1,,xn1 ,即可设
l i ( x ) = ( x − x 0 ) ( x − x i ) ⋯ ( x − x i − 1 ) ⋅ C ⋅ ( x − x i + 1 ) ⋯ ( x − x n − 1 ) = C ∏ k = 0 , k ≠ i n − 1 ( x − x k ) l_{i}(x)=\left(x-x_0\right)\left(x-x_{i}\right) \cdots\left(x-x_{i-1}\right) \cdot \mathrm{C} \cdot\left(x-x_{i+1}\right) \cdots\left(x-x_{n-1}\right)=\mathrm{C} \prod_{k=0, k \neq i}^{n-1}\left(x-x_{k}\right) li(x)=(xx0)(xxi)(xxi1)C(xxi+1)(xxn1)=Ck=0,k=in1(xxk)
再由 l i ( x i ) = 1 l_{i}\left(x_{i}\right)=1 li(xi)=1 ,即可确定它的常系数为 C = 1 ∏ k = 0 , k ≠ i ( x i − x k ) \mathrm{C}=\frac{1}{\prod_{k=0, k \neq i}\left(x_{i}-x_{k}\right)} C=k=0,k=i(xixk)1 ,最后得到插值基函数为:
l i ( x ) = ∏ k = 0 , k ≠ i n − 1 ( x − x k ) ∏ k = 0 , k ≠ i n − 1 ( x i − x k ) = ∏ k = 0 , k ≠ i n − 1 x − x k x i − x k ( i = 0 , 1 , 2 , ⋯   , n − 1 ) l_{i}(x)=\frac{\prod_{k=0, k \neq i}^{n-1}\left(x-x_{k}\right)}{\prod_{k=0, k \neq i}^{n-1}\left(x_{i}-x_{k}\right)}=\prod_{k=0, k \neq i}^{n-1} \frac{x-x_{k}}{x_{i}-x_{k}} \quad(i=0,1,2, \cdots, n-1) li(x)=k=0,k=in1(xixk)k=0,k=in1(xxk)=k=0,k=in1xixkxxk(i=0,1,2,,n1)
这样就可得到 n n n 个插值基函数 l i ( x ) ( i = 0 , 1 , 2 , ⋯   , n − 1 ) l_{i}(x)(i=0,1,2, \cdots, n-1) li(x)(i=0,1,2,,n1) ,代入 (12) 式,就得到Lagrange插值公 式:
P n − 1 ( x ) = ∑ i = 0 n − 1 l i ( x ) ⋅ z i = ∑ i = 0 n − 1 ( ∏ k = 0 , k ≠ i n − 1 x − x k x i − x k ) ⋅ z i (13) \tag{13} P_{n-1}(x)=\sum_{i=0}^{n-1} l_{i}(x) \cdot z_{i}=\sum_{i=0}^{n-1}\left(\prod_{k=0, k \neq i}^{n-1} \frac{x-x_{k}}{x_{i}-x_{k}}\right) \cdot z_{i} Pn1(x)=i=0n1li(x)zi=i=0n1 k=0,k=in1xixkxxk zi(13)
Lagrange插值公式具有以下特点:

  • 对称性: P n − 1 ( x ) P_{n-1}(x) Pn1(x) 与插值节点的排列顺序无关,只与 ( x i , z i ) ( i = 0 , 1 , 2 , ⋯   , n − 1 ) \left(x_{i}, z_{i}\right)(i=0,1,2, \cdots, n-1) (xi,zi)(i=0,1,2,,n1) 有关。
  • n = 1 n=1 n=1 为线性插值公式, n = 2 n=2 n=2 为抛物线插值公式。
  • 当插值节点数变化时,基函数需要重新计算。

2.4.2 C++实现

由于线性插值和抛物线插值均可以认为是特殊的Lagrange插值,所以这边就用C++简单实现下Lagrange插值。代码仓库见于github。

例: 已知采样值为:
x : 1.1 2.3 3.9 5.1 y : 3.887 4.276 4.651 2.117 \begin{array}{lllll} x: & 1.1 & 2.3 & 3.9 & 5.1 \\ y: & 3.887 & 4.276 & 4.651 & 2.117 \end{array} x:y:1.13.8872.34.2763.94.6515.12.117
用C++ 实现Lagrange插值计算在 2.101 2.101 2.101 4.234 4.234 4.234 两处的插值函数值。

//
// Created by CHH3213 on 2022/9/12.
//
#include 
#include 
#include
using namespace std;


double Lagrange(vector<vector<double>> points,double x_p){
    /**
     * points: 插值节点的坐标(x_i,z_i)集合
     * x_p: 为需计算的插值函数值的横坐标
     * return: 插值函数值
     */
     double  res=0;
    int items = points.size();//插值点个数
    for(int i=0;i<items;i++){
        double nume=1;//分子
        double deno=1;//分母
        for(int k=0;k<items;k++){
            if(k!=i){
                nume*=(x_p-points[k][0]);
                deno*=(points[i][0]-points[k][0]);
            }

        }
        res+=nume/deno*points[i][1];
    }

    return res;
}

int main(){
    vector<vector<double>> points={{1.1,3.887},{2.3,4.276},{3.9,4.651},{5.1,2.117}};
    cout<<"2.101: "<< Lagrange(points,2.101)<<endl;
    cout<<"4.234: "<< Lagrange(points,4.234)<<endl;
    return 0;
}

结果为:

2.101: 4.14569
4.234: 4.30074

3. 牛顿差商公式、样条插值*

用的比较少,所以带个星号。

3.1 牛顿差商公式

牛顿差商公式是另外一种给出插值多项式表达式的方法。对函数 h ( x ) h(x) h(x) ,分点 x i , i = 1 , … , n x_i, i=1, \ldots, n xi,i=1,,n ,定义各阶差商为:
h [ x i ] = h ( x i ) h [ x i , x j ] = h ( x j ) − h ( x i ) x j − x i h [ x i , x j , x k ] = h [ x j , x k ] − h [ x i , x j ] x k − x i … … h [ x 1 , x 2 , … , x n ] = h [ x 2 , x 3 , … , x n ] − h [ x 1 , x 2 , … , x n − 1 ] x n − x 1 (14) \tag{14} \begin{aligned} h\left[x_i\right] &=h\left(x_i\right) \\ h\left[x_i, x_j\right] &=\frac{h\left(x_j\right)-h\left(x_i\right)}{x_j-x_i} \\ h\left[x_i, x_j, x_k\right] &=\frac{h\left[x_j, x_k\right]-h\left[x_i, x_j\right]}{x_k-x_i} \\ & \ldots \ldots \\ h\left[x_1, x_2, \ldots, x_n\right] &=\frac{h\left[x_2, x_3, \ldots, x_n\right]-h\left[x_1, x_2, \ldots, x_{n-1}\right]}{x_n-x_1} \end{aligned} h[xi]h[xi,xj]h[xi,xj,xk]h[x1,x2,,xn]=h(xi)=xjxih(xj)h(xi)=xkxih[xj,xk]h[xi,xj]……=xnx1h[x2,x3,,xn]h[x1,x2,,xn1](14)
h [ x 1 , x 2 , … , x n ] h\left[x_1, x_2, \ldots, x_n\right] h[x1,x2,,xn] 关于自变量对称, 即以任意自变量次序计算 h [ x 1 , x 2 , … , x n ] h\left[x_1, x_2, \ldots, x_n\right] h[x1,x2,,xn] 结果都相同。
利用牛顿差商公式也可以得到多项式插值公式
h ( x ) = P n − 1 ( x ) + R n ( x ) (15-1) \tag{15-1} \begin{aligned} h(x)=& P_{n-1}(x)+R_n(x) \\ \end{aligned} h(x)=Pn1(x)+Rn(x)(15-1)
P n − 1 ( x ) = h ( x 1 ) + ( x − x 1 ) h [ x 1 , x 2 ] + ( x − x 1 ) ( x − x 2 ) h [ x 1 , x 2 , x 3 ] + ⋯ + ( x − x 1 ) ( x − x 2 ) ⋯ ( x − x n − 1 ) h [ x 1 , x 2 , … , x n ] (15-2) \tag{15-2} \begin{aligned} P_{n-1}(x)=& h\left(x_1\right)+\left(x-x_1\right) h\left[x_1, x_2\right] \\ &+\left(x-x_1\right)\left(x-x_2\right) h\left[x_1, x_2, x_3\right] \\ &+\cdots \\ &+\left(x-x_1\right)\left(x-x_2\right) \cdots\left(x-x_{n-1}\right) h\left[x_1, x_2, \ldots, x_n\right] \\ \end{aligned} Pn1(x)=h(x1)+(xx1)h[x1,x2]+(xx1)(xx2)h[x1,x2,x3]++(xx1)(xx2)(xxn1)h[x1,x2,,xn](15-2)
R n ( x ) = ( x − x 1 ) ( x − x 2 ) ⋯ ( x − x n − 1 ) ( x − x n ) ⋅ h [ x 1 , x 2 , … , x n , x ] (15-3) \tag{15-3} \begin{aligned} R_n(x)=&\left(x-x_1\right)\left(x-x_2\right) \cdots\left(x-x_{n-1}\right)\left(x-x_n\right) \\ & \cdot h\left[x_1, x_2, \ldots, x_n, x\right] \end{aligned} Rn(x)=(xx1)(xx2)(xxn1)(xxn)h[x1,x2,,xn,x](15-3)
其中 P n − 1 ( x ) P_{n-1}(x) Pn1(x) n − 1 n-1 n1 次插值多项式,根据根据(2.3)小节定理可知 P n − 1 ( x ) P_{n-1}(x) Pn1(x) 与Lagrange插值多项式相同。 R n ( x ) R_n(x) Rn(x) 为 余项,关于余项估计有:
h [ x 1 , x 2 , … , x n , x ] = h ( n ) ( η ) n ! , h\left[x_1, x_2, \ldots, x_n, x\right]=\frac{h^{(n)}(\eta)}{n !}, h[x1,x2,,xn,x]=n!h(n)(η),
其中 η ∈ [ min ⁡ ( x 1 , x 2 , … , x n , x ) , max ⁡ ( x 1 , x 2 , … , x n , x ) ] \eta \in\left[\min \left(x_1, x_2, \ldots, x_n, x\right), \max \left(x_1, x_2, \ldots, x_n, x\right)\right] η[min(x1,x2,,xn,x),max(x1,x2,,xn,x)]

3.2 样条插值

如果有 n n n 个点 { ( x i , z i ) , i = 1 , 2 , … , n } \left\{\left(x_i, z_i\right), i=1,2, \ldots, n\right\} {(xi,zi),i=1,2,,n} 要插值,当 n n n 较大时,用 n − 1 n-1 n1 阶插值多项式可以通过这些点,但 是得到的曲线会过于复杂, 与真实值差距很大,如果用插值函数计算 { ( x i , z i ) , i = 1 , 2 , … , n } \left\{\left(x_i, z_i\right), i=1,2, \ldots, n\right\} {(xi,zi),i=1,2,,n} 所在区间外 的点则误差更大。如果仅仅用线段连接或者用抛物线连接, 那么在两段交界的地方又不够光滑。

下图用 几种方法对函数 h ( x ) = 1 / ( 1 + x 2 ) h(x)=1 /\left(1+x^2\right) h(x)=1/(1+x2) x ∈ [ − 4 , 4 ] x \in[-4,4] x[4,4] 进行了插值,只用到了7个已知点。从图中可以看出,

  • 线性插值可能在连接两段的地方形成尖角转弯;
  • 抛物线插值在两段连接的地方也有明显转折;
  • 用通过给定 的7个点的 6 阶多项式插值,出现了很大的波折,与真实函数差距较大;
  • 样条插值也是用分段的多项式进行 插值,但样条插值保证连接处是光滑的,同时构成的曲线又不会太复杂。
数值分析 |多项式插值、牛顿插值、样条插值_第1张图片

设已知 n n n 个点 { ( x i , z i ) , i = 1 , … , n } , x 1 < x 2 < ⋯ < x n \left\{\left(x_i, z_i\right), i=1, \ldots, n\right\} , x_1{(xi,zi),i=1,,n}x1<x2<<xn, 求有二阶连续导数的 S ( x ) S(x) S(x) 使得 S ( x ) S(x) S(x) 通过这 n n n 个点, 即求 S ( x ) S(x) S(x) 使
{ S ( x i ) = z i , i = 1 , … , n min ⁡ S ∫ ∣ S ′ ′ ( x ) ∣ 2 d x \left\{\begin{array}{l} S\left(x_i\right)=z_i, i=1, \ldots, n \\ \min _S \int\left|S^{\prime \prime}(x)\right|^2 d x \end{array}\right. {S(xi)=zi,i=1,,nminSS′′(x)2dx
满足条件的函数就是三次样条函数。

三次样条函数是分段函数,以各 x i x_i xi 为分界点,称 { x 1 , x 2 , … , x n } \left\{x_1, x_2, \ldots, x_n\right\} {x1,x2,,xn} 为 结点(knots),三次样条函数 S ( x ) S(x) S(x) 在每一段内为三次多项式,其一阶导数 S ′ ( x ) S^{\prime}(x) S(x) 连续,为分段二次多项式, 其二阶导数 S ′ ′ ( x ) S^{\prime \prime}(x) S′′(x) 连续,为分段线性函数。

样条插值优点是保证了曲线光滑,可以对比较光滑的各种形状的函数进行插值同时插值曲线不会太复杂。

为了求样条函数 S ( x ) S(x) S(x) 的每一段的表达式,记 d j = x j − x j − 1 , j = 2 , … , n d_j=x_j-x_{j-1}, j=2, \ldots, n dj=xjxj1,j=2,,n 。因为 S ′ ′ ( x ) S^{\prime \prime}(x) S′′(x) 分段线性,可记 S ′ ′ ( x j ) = M j S^{\prime \prime}\left(x_j\right)=M_j S′′(xj)=Mj ,用线性插值公式,对 x ∈ [ x j − 1 , x j ] x \in\left[x_{j-1}, x_j\right] x[xj1,xj]
S ′ ′ ( x ) = M j − 1 ( x j − x ) d j + M j ( x − x j − 1 ) d j , S^{\prime \prime}(x)=\frac{M_{j-1}\left(x_j-x\right)}{d_j}+\frac{M_j\left(x-x_{j-1}\right)}{d_j}, S′′(x)=djMj1(xjx)+djMj(xxj1),
积分得
S ′ ( x ) = c 1 + ( − 1 ) M j − 1 ( x j − x ) 2 2 d j + M j ( x − x j − 1 ) 2 2 d j , S ( x ) = c 1 x + c 2 + M j − 1 ( x j − x ) 3 6 d j + M j ( x − x j − 1 ) 3 6 d j \begin{aligned} S^{\prime}(x) &=c_1+(-1) \frac{M_{j-1}\left(x_j-x\right)^2}{2 d_j}+\frac{M_j\left(x-x_{j-1}\right)^2}{2 d_j}, \\ S(x) &=c_1 x+c_2+\frac{M_{j-1}\left(x_j-x\right)^3}{6 d_j}+\frac{M_j\left(x-x_{j-1}\right)^3}{6 d_j} \end{aligned} S(x)S(x)=c1+(1)2djMj1(xjx)2+2djMj(xxj1)2,=c1x+c2+6djMj1(xjx)3+6djMj(xxj1)3

改写为
S ( x ) = M j − 1 ( x j − x ) 3 + M j ( x − x j − 1 ) 3 6 d j + c 1 ′ x j − x d j + c 2 ′ x − x j − 1 d j . S(x)=\frac{M_{j-1}\left(x_j-x\right)^3+M_j\left(x-x_{j-1}\right)^3}{6 d_j}+c_1^{\prime} \frac{x_j-x}{d_j}+c_2^{\prime} \frac{x-x_{j-1}}{d_j} . S(x)=6djMj1(xjx)3+Mj(xxj1)3+c1djxjx+c2djxxj1.
根据 S ( x j − 1 ) = z j − 1 S\left(x_{j-1}\right)=z_{j-1} S(xj1)=zj1 S ( x j ) = z j S\left(x_j\right)=z_j S(xj)=zj 解出 c 1 ′ , c 2 ′ c_1^{\prime}, c_2^{\prime} c1,c2 ,有
S ( x ) = M j − 1 ( x j − x ) 3 + M j ( x − x j − 1 ) 3 6 d j + ( z j − 1 − M j − 1 d j 2 6 ) x j − x d j + ( z j − M j d j 2 6 ) x − x j − 1 d j , x ∈ [ x j − 1 , x j ] . \begin{aligned} S(x)=& \frac{M_{j-1}\left(x_j-x\right)^3+M_j\left(x-x_{j-1}\right)^3}{6 d_j} \\ &+\left(z_{j-1}-\frac{M_{j-1} d_j^2}{6}\right) \frac{x_j-x}{d_j}+\left(z_j-\frac{M_j d_j^2}{6}\right) \frac{x-x_{j-1}}{d_j}, \\ & x \in\left[x_{j-1}, x_j\right] . \end{aligned} S(x)=6djMj1(xjx)3+Mj(xxj1)3+(zj16Mj1dj2)djxjx+(zj6Mjdj2)djxxj1,x[xj1,xj].
只要求出 M j , j = 1 , … , n M_j, j=1, \ldots, n Mj,j=1,,n ,则三次样条插值函数 S ( x ) S(x) S(x) 在每一段的表达式就完全确定。

S ′ ( x j − 0 ) = S ′ ( x j + 0 ) , j = 2 , … , n − 1 S^{\prime}\left(x_j-0\right)=S^{\prime}\left(x_j+0\right), j=2, \ldots, n-1 S(xj0)=S(xj+0),j=2,,n1 可以得到 { M j } \left\{M_j\right\} {Mj} n − 2 n-2 n2 个线性方程, 每一方程只涉及 M j − 1 , M j , M j + 1 M_{j-1}, M_j, M_{j+1} Mj1,Mj,Mj+1. 再增加两个线性限制条件可以解出 { M j , j = 1 , … , n } \left\{M_j, j=1, \ldots, n\right\} {Mj,j=1,,n} 。比如, 加限制条件 M 1 = 0 , M n = 0 M_1=0, M_n=0 M1=0,Mn=0 , 即在边界处函数为线性函数,这样解出的样条插值函数称为自然样条

样条函数除了可以用于插值,还可以用于平滑点 ( x i , z i ) , i = 1 , 2 , … , n \left(x_i, z_i\right), i=1,2, \ldots, n (xi,zi),i=1,2,,n 。插值函数需要穿过所有已知 点,而平滑则只要与已知点很接近就可以了。用样条函数在点 ( x i , z i ) , i = 1 , 2 , … , n \left(x_i, z_i\right), i=1,2, \ldots, n (xi,zi),i=1,2,,n 处进行平滑叫做样条回归,结果是以 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,,xn 为结点的三次样条函数,但在 x i x_i xi 处的值不需要等于 z i z_i zi

样条回归是使得
Q ( S ) = ∑ i = 1 n ( z i − S ( x i ) ) 2 + λ n ∫ ∣ S ′ ′ ( x ) ∣ 2 d x Q(S)=\sum_{i=1}^n\left(z_i-S\left(x_i\right)\right)^2+\lambda n \int\left|S^{\prime \prime}(x)\right|^2 d x Q(S)=i=1n(ziS(xi))2+λnS′′(x)2dx
最小的函数,其中 λ > 0 \lambda>0 λ>0 是代表光滑程度的参数, λ \lambda λ 越大得到的样条函数越光滑。

此外,还有B样条曲线、贝塞尔曲线等常见的曲线。

你可能感兴趣的:(数学,机器学习,算法,数据插值,数值分析)