MATLAB插值方法全解析:分段线性、多项式与三次样条的工程应用
2026/9/17 14:48:26 网站建设 项目流程

简介:在数学建模中,离散数据往往需要通过插值或拟合构建连续模型。这份PDF以插值方法为主线,通过三个典型案例展示如何从已知样点推算未知数值,面向正在学习数值分析、备战数学建模竞赛的读者。资源详细推导了分段线性插值的折线连接公式,说明其简单易用但无法形成光滑曲线的局限;随后介绍多项式插值,强调当多项式阶数与数据点数一致时存在唯一解,并给出牛顿差商构造与拉格朗日基函数两种实现形式;最后引入工程中广泛采用的三次样条插值,说明其分段光滑、稳定性好的特点。案例部分包括利用MATLAB的interp1函数对地图边界进行线性插值,结合数值积分估算国土面积,也有凸轮柱高插值等工程实例,便于读者理解方法选择与实际建模步骤。资源共1个PDF文件,大小仅258KB,下载后可快速翻阅,目前已有141人学习查看,适合用于课程巩固或赛前查漏补缺。

1. 从离散测量点到连续函数:插值方法在数学建模中的第一课

一张欧洲国家的地图摆在面前,要算出国土面积,手上只有边界上一组离散测量点,没有边界函数表达式——这是数学建模里最典型的插值应用场景。插值方法要解决的问题,就是由实验或测量得到的一批离散样点建立连续函数关系,或者求出样点之外任意位置的数值。数学建模竞赛中,插值几乎是每个队伍都会用到的底层工具,但真正把线性插值、多项式插值、样条插值的适用边界讲清楚的资料并不多。这篇案例分析的价值在于:它用三个工程实例把三种插值方法的数学条件、MATLAB 实现和精度陷阱串了一遍。反直觉的结论是——插值多项式的次数越高,结果往往越不可靠,三次样条比高次多项式更实用。本文适合备战国赛、华为杯的参赛者,也适合处理实验数据的工程师直接抄代码。

2. 分段线性插值:国土面积测算中的折线与收敛性

2.1 插值问题的数学提法与适用前提

先建立插值问题的标准提法:给定 n+1 个离散点 (x0, y0), (x1, y1), ..., (xn, yn),要求构造一个函数 P(x),使得 P(xi) = yi 对所有 i 成立。这里 x0 < x1 < ... < xn,即横坐标严格递增、节点互异。这个条件不是可有可无的——如果横坐标有重复或乱序,插值结果会直接出错,后面第 5 章会专门讲这个问题。

插值方法和拟合方法的本质区别在于:插值要求逼近函数严格穿过每一个已知数据点,拟合允许函数与数据点之间存在偏差。这个区别决定了它们在数学建模中的分工:测量精度高的数据用插值,带噪声的数据用拟合。案例中的地图边界测量数据精度较高,所以采用插值,而不是最小二乘拟合。这一点在很多建模论文里被混淆,写错会直接影响评阅印象分。

2.2 分段线性插值的公式与收敛性

分段线性插值的做法最直观:把相邻数据点用直线段连接起来。设 a = x0 < x1 < ... < xn = b,则在区间 [xi-1, xi] 上,插值函数为:

P(x) = (x - xi)/(xi-1 - xi) * yi-1 + (x - xi-1)/(xi - xi-1) * yi,xi-1 < x ≤ xi

这个公式本质上是以 xi-1 和 xi 为端点的线性加权,权重分别是 (x - xi)/(xi-1 - xi) 和 (x - xi-1)/(xi - xi-1),两者之和恒为 1。当 x 越接近左端点 xi-1,第一项权重越大,函数值越接近 yi-1;反之接近 yi。

分段线性插值的好处是计算量小、不会出现振荡,且可以证明当分点足够细时插值收敛于真实函数。代价是导数不连续,在节点处存在折角,整条曲线不光滑。对于本例要计算国土面积这种积分型问题,折角并不影响面积精度,所以线性插值完全够用。若要做曲线外观还原或求导,线性插值就不合适了。

2.3 案例实现:MATLAB 计算国土面积

原始数据包含 27 个分点,每个分点测量南边界 y1 和北边界 y2,单位毫米。先用 interp1 做线性插值加密边界,再用矩形法求两条边界之间的面积。核心代码如下:

clear all x = [7.0 10.5 13.0 17.5 34.0 40.5 44.5 48.0 56.0 ... 61.0 68.5 76.5 80.5 91.0 96.0 101.0 104.0 106.5 ... 111.5 118.0 123.5 136.5 142.0 146.0 150.0 157.0 158.0]; y1 = [44 45 47 50 50 38 30 30 34 36 34 41 45 46 43 37 ... 33 28 32 65 55 54 52 50 66 66 68]; y2 = [44 59 70 72 93 100 110 110 110 117 118 116 118 118 ... 121 124 121 121 121 122 116 83 81 82 86 85 68]; newx = 7:0.1:158; % 以 0.1mm 步长加密横坐标 newy1 = interp1(x, y1, newx, 'linear'); % 下边界线性插值 newy2 = interp1(x, y2, newx, 'linear'); % 上边界线性插值 Area = sum(newy2 - newy1) * 0.1 / 18^2 * 1600

这里 interp1 的四个参数依次是:已知节点横坐标、已知节点纵坐标、待插值点横坐标、插值方法字符串。'linear' 即分段线性插值,是 interp1 的默认方法。newx 用 7:0.1:158 生成了 1511 个插值点,每相邻两个插值点间距 0.1mm。sum(newy2 - newy1) * 0.1 是矩形法求面积的离散形式——每一个小矩形的宽是 0.1mm,高是上下边界差,全部加起来就是地图上的面积(平方毫米)。

2.4 精度来源:步长、区间划分与积分近似

最后一步单位换算是本例最容易抄错的地方:地图比例 18mm 相当于 40km,所以 1 平方毫米对应 (40/18)² 平方公里,即 1600/18²。代码里的 * 0.1 / 18^2 * 1600 连在一起就是:先乘小矩形宽度,再做单位换算。最终计算结果约为 42414 平方公里。

实际使用时,newx 的步长决定了矩形法近似的精度。步长越小,梯形或矩形逼近越精确,但计算量线性增长,同时受限于原始测量数据的密度——在原始节点非常稀疏的地方(比如 x=17.5 到 x=34 之间),即使把插值步长压到 0.01mm,新增的信息量也是零。更合理的做法是保留平滑误差和测量误差的平衡:对本例这样的线性插值,步长取原始最小间距的 1/10 到 1/20 即可,不需要无脑加密。另外要提醒一句:原 PDF 中的逗号和引号是中文全角符号,粘贴到 MATLAB 前要全部改成半角,否则会报错。

3. 多项式插值:凸轮轮廓设计中的 Runge 振荡与次数红线

3.1 凸轮轮廓为什么需要连续函数

第二个案例来自万能拉拨机中的圆柱形凸轮设计。底圆半径 R=300mm,上端面高度随角度变化,设计时把底圆周 18 等分,得到 19 个分点的高度数据(第 0 和第 18 个分点重合,高度相同,都是 502.8mm)。数控加工需要知道圆周上任意角度对应的高度,而不只是这 19 个离散点——这就是插值点处的数值求解问题。

clear; close; x = linspace(0, 2*pi*300, 19); % 展开底圆,19 个等距分点 y = [502.8 525.0 514.3 451.0 326.5 188.6 92.2 59.6 62.2 102.7 ... 147.1 191.6 236.0 280.5 324.9 369.4 413.8 458.3 502.8]; plot(x, y, 'o'); % 散点图观察数据形态 axis([0 2000 0 550]);

这里 x 用 linspace 生成 0 到 2πR 的 19 个等距点,相当于把圆柱面展开成平面,高度 y 随展开方向变化。先画散点图是为了确认数据形态——曲线在 x=1000 附近出现明显低谷,整体呈周期性变化。这个形状用三次多项式插值可以复现,但如果贸然用 18 次全局多项式去穿过全部 19 个点,就会触发 Runge 振荡。

3.2 多项式插值的存在唯一性与 Runge 振荡

多项式插值的理论依据是:存在唯一的 n 次多项式通过 n+1 个互异节点。设 P(x) = a0xⁿ + a1xⁿ⁻¹ + ... + aₙ,代入 n+1 个节点得到一个关于系数 a0, a1, ..., aₙ 的线性方程组。当 m = n 且节点横坐标互异时,系数矩阵是 Vandermonde 矩阵,行列式不为零,解存在且唯一。

问题是:唯一存在不代表结果可用。在等距节点上用高次多项式插值,区间两端会出现剧烈振荡,这就是 Runge 现象。典型例子是用高次多项式逼近 f(x) = 1/(1+25x²) 时,插值多项式在两端的误差随次数增加不降反升。本例数据只有 19 个点,如果硬用 18 次全局多项式,边缘区域的高度值会被振荡放大到完全偏离物理事实,加工出来的凸轮表面会出现波浪形误差。数值分析教材的通行经验是:多项式插值次数尽量控制在 7 次以内,超过 7 次改用样条或分段低次插值。这与机器学习里的过拟合是同一类问题——模型自由度超过数据信息量,拟合精度高但泛化能力差。

3.3 Lagrange 插值公式与数值计算组织

若只需求插值点处数值而不想显式解出系数,Lagrange 插值公式是标准工具:

Pn(x) = Σᵢ yᵢ · Πⱼ≠ᵢ (x - xⱼ)/(xᵢ - xⱼ)

每个基函数 Πⱼ≠ᵢ (x - xⱼ)/(xᵢ - xⱼ) 在节点 xᵢ 处取值 1,在其余节点处取值 0,因此整个求和式在节点处严格等于对应纵坐标。Lagrange 形式的好处是公式直接、不用解方程组,坏处是每增加一个节点所有基函数都要重算,工程上一般用它做理论推导,实际计算用 Newton 形式或直接调 MATLAB 函数。

3.4 案例实现:用 cubic 方法做分段三次插值

对于凸轮数据,MATLAB 里更稳妥的做法是分段三次插值,使用 interp1 的 'cubic' 参数:

xi = 0:2*pi*300; % 从 0 到展开后周长,步长默认 1 yi = interp1(x, y, xi, 'cubic'); % 分段三次 Hermite 插值 plot(xi, yi);

注意这里的 'cubic' 并不是构造一个全局的三次多项式去穿所有点。MATLAB 的 interp1 在 'cubic' 模式下执行的是分段三次 Hermite 插值,每个小区间用三次多项式连接,且保证节点处函数值与一阶导数连续。它虽然名义上叫三次多项式插值,但本质是分段低次插值,因此不会出现全局高次插值的 Runge 振荡。这也是原文标题写"多项式插值"、实际代码用 'cubic' 不矛盾的原因——工程实现时用分段三次形式去逼近"多项式插值"的效果,既保留光滑性又规避振荡。若确实需要全局多项式插值,可以用 polyfit 配合 polyval,但本例数据规模下不推荐。

4. 样条插值:水塔用水率重构中的光滑性约束

4.1 三次样条的定义与 C² 连续性

第三个案例是居民区水塔用水规律分析。水塔高 12.2 米、直径 17.4 米,一天内水泵自动加水两次,测量得到 28 个时刻的水位,中间有 3 个时刻正在供水无法记录。需要从离散水位数据估算连续用水率,也就是流速函数 f(t)。这个问题对光滑性的要求比前两个案例高:用水率是水位的二阶导数,两次求导会放大数据噪声,如果只用分段线性插值,得到的流速曲线会严重锯齿化。

三次样条插值恰好满足这个需求。数学定义是:设 a = x0 < x1 < ... < xn = b,分段函数 S(x) 称为 k 次样条,需满足两个条件:一是在每个小区间上是次数不超过 k 的多项式;二是在整个 [a,b] 上具有直到 k-1 阶连续导数。工程上最常用的是三次样条(k=3),它在每个小区间上是三次多项式,在整个区间上函数值、一阶导数、二阶导数都连续,即 C² 连续。直观理解就是:不仅曲线本身连续,曲率变化也平滑,不会出现折角。

样条插值与分段三次 Hermite 插值的区别是:Hermite 只保证 C¹ 连续,样条通过联立节点处二阶导数连续的方程,把光滑性提升到 C²;代价是需要额外补充边界条件(常用自然样条,即端点二阶导数为零)。

4.2 从水位到流速:体积换算与差商公式

先用体积公式把水位换算成体积:

V = (π/4) * d² * h = (π/4) * 17.4² * h ≈ 237.79h

这里的核心是估算流速 f(t) = -dV/dt,负号表示水位下降时体积减少、用水为正。为提高精度,原文用二阶差商(即二阶导数的差分近似)来估算 ti 时刻的流速。由于测量时刻并不等距,且数据被水泵两次工作分割成三组,每组数据的前两个和后两个点不能使用中心差商,需要改用向前或向后差商。

三种差商公式如下:

公式类型表达式适用位置
中心差商(-vᵢ₊₂ + 8vᵢ₊₁ - 8vᵢ₋₁ + vᵢ₋₂) / (12(tᵢ₊₁ - tᵢ))每组中间数据
向前差商(-vᵢ₊₂ + 4vᵢ₊₁ - 3vᵢ) / (2(tᵢ₊₁ - tᵢ))每组开头两个点
向后差商(3vᵢ - 4vᵢ₋₁ + vᵢ₋₂) / (2(tᵢ - tᵢ₋₁))每组末尾两个点

中心差商的系数来自 Taylor 展开:-v(x+2h) + 8v(x+h) - 8v(x-h) + v(x-2h) 除以 12h,是对 v''(x) 的四阶精度近似,误差项为 O(h⁴)。向前和向后差商是三点格式,精度降为二阶。为什么不用更简单的一阶差商?因为一阶差商对测量误差的敏感度太高,水位读数的小误差在除以小时级时间间隔后会被放大几十倍,流速曲线会呈现严重的尖峰。用二阶差商的另一个好处是它天然对应流速变化的加速度信息,让后续样条插值更容易捕捉用水高峰。

4.3 案例实现:散点图与三次样条插值

先用 MATLAB 画出流速散点图,数据取自原文测量记录:

t = [0 0.921 1.843 2.949 3.871 4.978 5.9 7.006 7.982 ... 8.967 10.954 12.032 12.954 13.875 14.982 15.903 ... 16.826 17.931 19.037 19.959 20.839 22.958 23.88 ... 24.986 25.908]; r = [54.516 42.320 38.085 41.679 33.297 37.814 30.748 ... 38.455 32.122 41.718 73.686 76.434 71.686 60.19 ... 68.333 59.217 52.011 56.626 63.023 54.859 55.439 ... 57.602 57.766 51.891 36.464]; plot(t, r, 'b+'); % 流速散点图 title('流速散点图'); xlabel('时间(小时)'); ylabel('流速(立方米/小时)');

观察散点图可以发现:两个水泵工作时段(约 9 点到 11 点、20.8 点到 22 点之间)流速数据缺失,散点分布呈现明显的三段结构。三次样条插值可以直接跨过缺测区段,在两段数据之间生成平滑过渡,这在物理上比每段单独插值更合理——水泵启动瞬间流量突变是真实存在的,但突变前后曲线不应出现阶跃折角。

接着用 spline 方法重构连续用水率函数:

x0 = t; y0 = r; % 已知流速节点 [l, n] = size(x0); dl = x0(n) - x0(1); % 总时间跨度 x = x0(1):1/3600:x0(n); % 被插值点:按秒加密 ys = interp1(x0, y0, x, 'spline'); % 三次样条插值 plot(x, ys); title('样条插值下的流速图'); xlabel('时间(小时)'); ylabel('流速(立方米/小时)');

这里 x0(1):1/3600:x0(n) 表示从第 0 小时到第 25.908 小时,按 1/3600 小时(即 1 秒)的步长生成插值点,用于输出高分辨率流速曲线。spline 方法在 MATLAB 中实现的是真正的三次样条插值,节点处二阶导数连续,曲线更光滑;横向对比 2.3 节的 'linear' 数据,spline 的计算代价更高,但优势在于可以直接对插值结果求导而不会出现一阶导数跳变。对于后续要计算日总用水量(即流速函数在时间上的积分),样条插值的面积误差也明显小于线性插值。

4.4 插值结果的使用边界

样条插值给出的流速曲线在缺测区段(9.981 到 10.954、20.839 到 22.958 小时)是纯数学推出来的光滑过渡,没有实测依据。如果要在论文里使用这段结果,建议把水泵工作时间段单独标注,说明该区间为断点插值,物理上对应水泵快速补水导致的负流量变化。这里也能看出插值和拟合在建模任务中的不同分工:已知散点求中间曲线用插值,要预测未来时段或反推测量误差则要用最小二乘拟合。原文写"先用差商估算流速再用样条插值"的流程,本质是把求导这个病态问题转化为两个适定问题的串联——先降噪(差商平滑),再加密(样条插值)。

5. interp1 方法选型:五种插值方式对比与三个关键参数陷阱

5.1 interp1 五种方法对比

把前面三个案例用到的 interp1 方法汇总,加上另外两个常用参数,一张表可以覆盖绝大部分选型需求:

方法参数实现方式光滑性计算开销适用场景
'nearest'最近邻插值不连续最低分类标签、离散状态量
'linear'分段线性C⁰面积估算、快速预览
'pchip'分段三次 Hermite数据有界且不能过冲
'cubic'分段三次 Hermite凸轮类曲线重构
'spline'三次样条水流速、应力应变曲线

注意 'pchip' 和 'cubic' 在某些 MATLAB 版本中行为一致,都保证分段三次多项式且在节点处 C¹ 连续,但 'pchip' 有明确的保形约束——它不会在单调递增的数据段内制造局部极值。这是样条做不到的:三次样条为了 C² 光滑,允许在数据段内出现轻微过冲。水塔例子里流速数据本身波动较大,用 spline 合理;如果是应力-应变曲线这类必须严格单调的数据,spline 反而要谨慎。

5.2 三个容易被忽略的参数陷阱

第一个陷阱是横坐标必须严格递增。interp1 要求 x 向量单调,如果原始测量顺序混乱,要先执行 [x, idx] = sort(x); y = y(idx)。这在处理从文件读入的实验数据时经常遇到。

第二个陷阱是待插值点不能超出 x 的范围。interp1 默认不支持外推,落在范围之外的点直接返回 NaN,曲线会在末端断裂。解决办法是加上 'extrap' 参数,或者用 interp1(x, y, xq, 'linear', 'extrap') 显式启用外推。但要注意外推的结果是纯数学推断,物理上是否成立需要自行判断。

第三个陷阱是数据中含 NaN。测量记录里常有因传感器故障产生的空值,interp1 遇到 NaN 会传染——只要参与插值的节点中有 NaN,整个区间结果都变成 NaN。标准做法是先用 isnan 找出坏点坐标,再用 fillmissing 或手工剔除,最后做插值。水塔案例里那 3 个无水位记录时刻在预处理时就是直接剔除的,而不是填 0。

5.3 一个快速验证插值可靠性的技巧

写一个三行的小脚本,用随机抽样的方式来检验插值结果对节点选择的敏感性:

idx = randperm(length(x), length(x) - 2); % 随机留出 2 个点 x_tr = x(idx); y_tr = y(idx); x_te = setdiff(x, x_tr); y_te = y(idx中的对应位置); y_pred = interp1(x_tr, y_tr, x_te, method); err = abs(y_pred - y_te) ./ max(abs(y_te), 1e-6); % 相对误差

实际操作时把这个脚本跑 50 遍以上,观察 error 的均值和最大值的分布。如果留出 2 个点后插值误差超过 5%,说明原始节点密度不足,加密测量或补测是比换插值方法更有效的改进路径;如果误差很小,再去做高分辨率插值才有意义。这个方法在数学建模论文里可以作为模型稳健性检验的论据,比单纯贴一张插值曲线图更有说服力。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询