一. 原理介绍
- 关于插值的定义及基本原理可以参照如下索引
插值原理(数值计算方法) - 前面已经介绍过插值原理的唯一性表述,对于分立的数据点,方程组:
P ( x 0 ) = y 0 ⇒ a 0 + a 1 x 0 + a 2 x 0 2 + ⋯ + a n x 0 n = y 0 , P ( x 1 ) = y 1 ⇒ a 0 + a 1 x 1 + a 2 x 1 2 + ⋯ + a n x 1 n = y 1 , ⋮ P ( x n ) = y n ⇒ a 0 + a 1 x n + a 2 x n 2 + ⋯ + a n x n n = y n . \begin{aligned} & P(x_0) = y_0 \quad \Rightarrow \quad a_0 + a_1 x_0 + a_2 x_0^2 + \cdots + a_n x_0^n = y_0, \\ & P(x_1) = y_1 \quad \Rightarrow \quad a_0 + a_1 x_1 + a_2 x_1^2 + \cdots + a_n x_1^n = y_1, \\ & \quad \vdots \\ & P(x_n) = y_n \quad \Rightarrow \quad a_0 + a_1 x_n + a_2 x_n^2 + \cdots + a_n x_n^n = y_n. \end{aligned} P(x0)=y0⇒a0+a1x0+a2x02+⋯+anx0n=y0,P(x1)=y1⇒a0+a1x1+a2x12+⋯+anx1n=y1,⋮P(xn)=yn⇒a0+a1xn+a2xn2+⋯+anxnn=yn.
恒有解,多项式插值的目标即为在这一过程中求解系数 a 0 、 a 1 、 . . . 、 a n ⟺ [ a 0 a 1 a 2 ⋮ a n ] a_0、a_1、...、a_n\Longleftrightarrow\begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_n \end{bmatrix} a0、a1、...、an⟺ a0a1a2⋮an
- 即解方程组:
[ 1 x 0 x 0 2 ⋯ x 0 n 1 x 1 x 1 2 ⋯ x 1 n ⋮ ⋮ ⋮ ⋱ ⋮ 1 x n x n 2 ⋯ x n n ] [ a 0 a 1 a 2 ⋮ a n ] = [ y 0 y 1 y 2 ⋮ y n ] . \begin{bmatrix} 1 & x_0 & x_0^2 & \cdots & x_0^n \\ 1 & x_1 & x_1^2 & \cdots & x_1^n \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_n & x_n^2 & \cdots & x_n^n \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_n \end{bmatrix}= \begin{bmatrix} y_0 \\ y_1 \\ y_2 \\ \vdots \\ y_n \end{bmatrix}. 11⋮1x0x1⋮xnx02x12⋮xn2⋯⋯⋱⋯x0nx1n⋮xnn a0a1a2⋮an = y0y1y2⋮yn .
关于该方程组的解法在线性代数中有多种,这里主要提及两种:
①高斯消元法
②克莱姆法则
程序设计过程中一般有封装好的库函数,如果为了考虑减少库依赖和提高程序运行效率及占用可能会用到上述方法(这里就不详细展开了)
二. 程序设计
1. 构建矩阵
A = np.zeros((n, n))
for i in range(n):
for j in range(n):
A[i, j] = x_data[i] ** j
Ⅰ 构建一个
(
n
×
n
)
(n \times n)
(n×n)的矩阵 A 来描述多项式矩阵:
[
1
x
0
x
0
2
⋯
x
0
n
1
x
1
x
1
2
⋯
x
1
n
⋮
⋮
⋮
⋱
⋮
1
x
n
x
n
2
⋯
x
n
n
]
\begin{bmatrix} 1 & x_0 & x_0^2 & \cdots & x_0^n \\ 1 & x_1 & x_1^2 & \cdots & x_1^n \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_n & x_n^2 & \cdots & x_n^n \end{bmatrix}
11⋮1x0x1⋮xnx02x12⋮xn2⋯⋯⋱⋯x0nx1n⋮xnn
其中:
A
[
i
]
[
j
]
=
x
i
j
A[i][j] = x_{i}^{j}
A[i][j]=xij
式中第一列的1是通过 x i 0 x_{i}^{0} xi0得到的。
B = np.array(y_data)
Ⅱ 构建系数矩阵 B,即原始数据对应的 y 值:
2. 求解矩阵方程
coefficients = np.linalg.solve(A, B)
使用Numpy自带函数linalg.solve()
解矩阵方程
注释:
np.linalg.solve(A, B)
求解出的系数数组的顺序是 从低到高次项,即:
coefficients[0]
为常数项( x 0 x^0 x0 的系数)coefficients[1]
为一次项( x 1 x^1 x1 的系数)coefficients[2]
为二次项( x 2 x^2 x2 的系数)
以此类推。
求解出矩阵形式形如
[ 6. -7.83333333 4.5 -0.66666667]
从左至右为最低次项到最高次项系数
3. 作出多项式函数
x_data, y_data = zip(*data)
Ⅰ 获取输入数据(方法不唯一)
x_vals = np.linspace(min(x_data) - 1, max(x_data) + 1, 500)
Ⅱ 在数据点区间内构造间隔点来使绘图更加平滑(matplotlib.pyplot
的局限性)
y_vals = np.polyval(coefficients[::-1], x_vals)
Ⅲ 通过Numpy内置函数np.polyval()
来构造多项式函数(需要指定多项式系数
),实现输入 x 值,输出通过构造的多项式函数对应的函数值。
注释: 前面注释提到
coefficients
数组中的系数对应从左到右为最低到最高次项系数,而函数np.polyval()
要求输入具有逆序的项系数:coefficients[::-1]
将变为从最高次到最低次项系数
np.polyval(coefficients[::-1], x_vals)
将计算每一个x_val
对应的多项式值,并返回一个y_vals
数组,包含每个x_val
对应的y
值。
4. 绘制插值曲线
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
通过替换显示字体('SimHei'
)和符号(False
)来使图例正常显示中文和负号
plt.plot(x_vals, y_vals, label="插值曲线", color='b')
plt.scatter(x_data, y_data, color='r', label="数据点")
plt.title("插值多项式")
plt.xlabel("X轴")
plt.ylabel("Y轴")
plt.legend()
plt.grid(True)
plt.show()
5. 完整代码
import numpy as np
import matplotlib.pyplot as plt
def construct_interpolation_polynomial(data):
# 提取x和y值
x_data, y_data = zip(*data)
n = len(data)
# 构造矩阵A (n x n)
A = np.zeros((n, n))
# 构造矩阵A的每一列, A[i][j] = x_i^(j)
for i in range(n):
for j in range(n):
A[i, j] = x_data[i] ** j
# 构造常数向量B,B[i] = y_i
B = np.array(y_data)
# 解线性方程组 A * coefficients = B
coefficients = np.linalg.solve(A, B)
return coefficients
def plot_interpolation(data, coefficients):
# 提取x和y值
x_data, y_data = zip(*data)
# 生成插值多项式的x和y值
x_vals = np.linspace(min(x_data) - 1, max(x_data) + 1, 500)
# 计算多项式的y值
y_vals = np.polyval(coefficients[::-1], x_vals)
# 绘图
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
plt.plot(x_vals, y_vals, label="插值曲线", color='b')
plt.scatter(x_data, y_data, color='r', label="数据点")
plt.title("插值多项式")
plt.xlabel("X轴")
plt.ylabel("Y轴")
plt.legend()
plt.grid(True)
plt.show()
# 定义输入数据 (xi, yi)
data = [
[1, 2],
[2, 3],
[3, 5],
[4, 4]
]
# 构造插值多项式的系数
coefficients = construct_interpolation_polynomial(data)
# 输出多项式的系数
print("插值多项式的系数:", coefficients)
# 绘制插值曲线
plot_interpolation(data, coefficients)
三. 图例

这要求我们的输入数据都具有上述形式:
data = [
[x_1, y_1],
[x_2, y_2],
[x_3, y_3],
[x_4, y_4],
...]
最后我们插值一组随机生成的测试数据
data = [
[7.264384, 3.931292],
[1.943873, 6.218903],
[8.384019, 2.584103],
[5.672210, 9.032674],
[0.294315, 4.726018],
[6.129531, 7.912846],
[9.516347, 1.478264],
[3.824679, 5.596042]
]

实际应用时应避免数据点过多导致的多项式次数过高
希望能够帮到迷途之中的你,知识有限,如有学术错误请及时指正,感谢大家的阅读
(^^)/▽ ▽\(^^)