数模比赛中,常常需要根据已知的函数点进行数据、模型的处理和分析,但可能出现数据极少或者数据缺失的情况,此时数据并不能支撑分析,这时候就需要用到一些数学的方法,去模拟产生一些新的但又比较靠谱的值来满足数据的需求。以上提到正是插值法的作用
设函数y=f(x)在区间[a,b]上有定义,且已知在点
a < = x 0 < x 1 < . . . < x n < = b a<=x_0
上的值分别为:
y 0 , y 1 , . . . < y n y_0,y_1,...
若存在一简单函数P(x),使得
P ( x i ) = y i ( i = 0 , 1 , 2 , . . . , n ) P(x_i)=y_i (i=0,1,2,...,n) P(xi)=yi(i=0,1,2,...,n)
则称P(x)为f(x)的插值函数,点x0,x1,…,xn称为插值节点,包括插值节点的区间[a,b]称为插值区间,求插值函数P(x)的方法称为插值法。
常用的三种插值法的概念
P ( x ) = a 0 + a 1 x + . . . + a n x n , P(x)=a_0+a_1x+...+a_nx^n, P(x)=a0+a1x+...+anxn,
本文只介绍多项式插值和分段插值。
红色是目标函数,蓝色是通过拉格朗日插值法模拟出来的函数图像。可以看到在次数增多时,两端图像产生明显的震荡。
- 多项式插值中常用的有拉格朗日插值法。但该方法在高次插值时会出现两端波动极大,产生明显的震荡,即产生龙格现象。因此不熟悉曲线运动趋势的前提下,不要轻易使用高次插值。加上函数难以使用,因此在数模比赛里多项式插值也很少使用
总结一下:
基于插值多项式的缺点,在数模比赛中通常会使用分段插值法
若新插入的值xi位于xj-1到xj之间,那么只需要模拟出xj-1到xj之间的插值函数即可。
Matlab有内置的函数,其实现过程已经帮我们封装好了,会调用就行了
函数原型
p=pchip(x,new_x)
x是已知的样本点的横坐标;y是已知的样本点的纵坐标;new_x是要插入对应的点的横坐标,通过pchip函数模拟出new_x对应的纵坐标
假设x的范围是[-pi,pi];y=sin(x);new_x=-pi:0.1:pi(从-pi到pi间隔0.1一个横坐标)
那么可以这样调用
x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p=pchip(x,y,new_x);%%p是通过Hermite插值法模拟出来的对应new_x的纵坐标
plot(x,y,'o',new_x,p,'r-');
legend('样本点','三次埃尔米特插值','Location','southeast');
可以看到样本点函数对应的是o点图,而埃尔米特插值法模拟出来的函数图像是红色-线
三次样条插值的matlab内置函数是
p = spline (x,y, new_x)
x是已知的样本点的横坐标;y是已知的样本点的纵坐标;new_x是要插入处对应的横坐标
同样的用三次样条插值法模拟出来new_x对应的图像
x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p1=pchip(x,y,new_x);%%p是通过Hermite插值法模拟出来的对应new_x的纵坐标
p2=spline(x,y,new_x);
plot(x,y,'r-',new_x,p1,'b.',new_x,p2,'g*');
legend('样本点','三次埃尔米特插值','三次样条插值','Location','southeast');
可以看出,三次样条生成的曲线更加光滑。在实际建模中, 由于我们不知道数据的生成过程,因此这两种插值都可以使用
先有2009到2018的中国人口数,通过三次埃尔米特插值预测或三次样条插值预测预测出2019到2023的中国人口数
year=2009:2018;
population=[133126,133770,134413,135069,135738,136427,137122,137866,138639, 139538];
p1=pchip(year,population,2019:2023);
p2=spline(year,population,2019:2023);
plot(year,population,'r-',2019:2023,p1,'b.',2019:2023,p2,'g*');
legend('样本点','三次埃尔米特插值预测','三次样条插值预测','Location','SouthEast')
另外若需要作出两张图形,需要在作图前标明是第几张图,否则系统判定是只在 figure(1)上作图,后来的图像会将前面的图像刷新掉
函数原型
p=interpn(x1,x2,...,xn,y,new_x1,new_x2,...,new_xn,method)
x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p2=spline(x,y,new_x);
等价于
x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p2=interpn(x,y,new_x,'spline');
x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p2=spline(x,y,new_x);
等价于
x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p2=interpn(x,y,new_x,'spline');