今天木木所要分享的是高阶插值多项式的振荡问题,初学插值函数的时候,常常在想,是不是取的节点越多,插值阶数越高,近似解就越精确呢?答案并不是这样的。当插值节点越多时,高次多项式插值经常会出现振荡现象,该多项式并不一致收敛于函数本身。我们从以下三个例题中感受基于Mathematica插值函数的振荡现象。
例1:给定函数f(x)=
pt=Table[{i,Sqrt[i]},{i,{0.49,0.64,0.81,1}}];(*构造插值节点*)
l[x_]=InterpolatingPolynomial[pt,x]//Expand(*插值多项式*)
t[x_]=Normal[Series[Sqrt[x],{x,1,3}]];(*泰勒展开式*)
{c1=Sqrt[0.98],c2=l[0.98],c1-c2,c3=t[0.98],c1-c3}
Needs["PlotLegends`"]
(*绘制f(x),l(x),t(x)*)
Plot[{Sqrt[x],l[x],t[x]},{x,0.49,1},
PlotStyle->{{Red,Thick,Dashed},Blue,Black},
AxesLabel->{x,y},AxesStyle->Thick,
BaseStyle->{FontSize->15,Bold},
PlotLegend->{Style["f(x)",14,Italic,Bold],
Style["l(x)",14,Italic,Bold],
Style["t(x)",14,Italic,Bold]},
LegendBorder->Thick,
LegendSize->{0.7,0.4}
]
(*绘制误差函数图*)
Plot[{Sqrt[x]-l[x],Sqrt[x]-t[x]},{x,0.49,1},
PlotStyle->{{Red,Thick,Dashed},Blue},
AxesLabel->{x,error},AxesStyle->Thick,
BaseStyle->{FontSize->15,Bold},
PlotLegend->{Style["f(x)-l(x)",14,Italic,Bold],
Style["f(x)-t(x)",14,Italic,Bold]},
LegendBorder->Thick,
LegendSize->{0.7,0.4}
]
得出三次插值多项式、三次泰勒多项式:
0.260062 + 1.11977 x - 0.523162 x^2 + 0.143332 x^3
1 + 1/2 (-1 + x) - 1/8 (-1 + x)^2 + 1/16 (-1 + x)^3
精确解 | 三次多项式 | 误差 | 三次泰勒 | 误差 |
0.989949 | 0.989893 | 0.0000567061 | 0.98995 | -6.33883e-9 |
如图所示,三次插值多项式还没表现“振荡现象”,函数的插值多项式误差在插值区间上分布均匀,而其泰勒多项式误差具有局部性质,即在泰勒展开点附近逼近效果较好,越远离该点,则逼近效果越差。
例2:给定函数f(x)=
pt = Table[{i^2, i}, {i, 0, 1, 0.1}];(*构造插值节点*)
l[x_] = InterpolatingPolynomial[pt, x] // Expand(*插值多项式*)
t[x_] = Normal[Series[Sqrt[x], {x, 1, 10}]](*泰勒展开式*)
Needs["PlotLegends`"]
(*绘制f(x),l(x),t(x)*)
Plot[{Sqrt[x], l[x], t[x]}, {x, 0, 1},
PlotStyle -> {{Red, Thick, Dashed}, Blue, Black},
AxesLabel -> {x, y}, AxesStyle -> Thick,
BaseStyle -> {FontSize -> 15, Bold},
PlotLegend -> {Style["f(x)", 14, Italic, Bold],
Style["l(x)", 14, Italic, Bold],
Style["t(x)", 14, Italic, Bold]},
LegendBorder -> Thick,
LegendSize -> {0.7, 0.4}
]
得出10次插值多项式、10次泰勒多项式:公式太长,这里不便给出,感兴趣的小伙伴可以自行运行~
由图可以看出,f(x)的10次插值函数l(x)发生了严重的振荡现象,其结果已无法使用,而10次泰勒多项式t(x)在零点附近逼近效果较差。
例3:给定f(x)=ln(1+x),
pt = Table[{i, Log[i + 1]}, {i, 0, 2, 0.2}];(*构造插值节点*)
InterpolatingPolynomial[pt, x] // Expand(*插值多项式*) =
Normal[Series[Log[x + 1], {x, 0, 10}]];(*泰勒展开式*) =
Needs["PlotLegends`"]
+ 1], l[x], t[x]}, {x, 0, 2},
PlotStyle -> {{Red, Thick, Dashed}, Blue, Black},
AxesLabel -> {x, y}, AxesStyle -> Thick,
BaseStyle -> {FontSize -> 15, Bold},
PlotLegend -> {Style["f(x)", 14, Italic, Bold],
14, Italic, Bold],
14, Italic, Bold]},
LegendBorder -> Thick,
LegendSize -> {0.7, 0.4}
]
这个例题主要说明使用泰勒展开式需注意其收敛域,当x>1时,泰勒展开式发散,而插值多项式吻合效果很好。
总结:插值具有整体性,但高次插值可能会发生振荡现象,泰勒展开式具有局部现象,在应用时必须注意收敛域,这样得出来的结果才有意义。