当前位置:   article > 正文

基于MATLAB的B样条插值拟合算法与分段多项式(附完整代码)_matlab分段拟合

matlab分段拟合

一. B样条函数

B样条函数的MATLAB代码如下:

  1. S=spapi(k,x,y)
  2. %k为用户选定的B样条阶次,一般以45居多

例题1

分别用B样条函数对y和f(x)中的自选数据进行5次B样条函数拟合,并与三次分段多项式样条函数拟合的结果相比较。

y=sin(t),\quad f(x)=(x^2-3x+5)e^{-5x}sinx

解:

MATLAB代码如下:

  1. clc;clear;
  2. %%y函数部分
  3. x0=[0,0.4,1,2,pi];
  4. y0=sin(x0);
  5. ezplot('sin(t)',[0,pi]);
  6. hold on
  7. %三次分段多项式样条插值
  8. sp1=csapi(x0,y0);
  9. fnplt(sp1,'--');
  10. %5次B样条插值
  11. sp2=spapi(5,x0,y0);
  12. fnplt(sp2,':')
  13. %%f(x)函数部分
  14. x=0:.12:1;
  15. y=(x.^2-3*x+5).*exp(-5*x).*sin(x);
  16. figure;
  17. ezplot('(x.^2-3*x+5).*exp(-5*x).*sin(x)',[0,1]),
  18. hold on
  19. sp1=csapi(x,y);
  20. fnplt(sp1,'--');
  21. sp2=spapi(5,x,y);
  22. fnplt(sp2,':')

运行结果:

二. 基于样条插值的数值微分

在MATLAB中,可以利用以下函数来求S的k阶导数:

Sd=fnder(S,k)

 如果是求多变量函数的偏导数,则格式如下:

Sd=fnder(S,[k1,...,kn])

例题2

任取函数f(x)的一些数据点,分别用三次分段多项式样条函数与B样条插值函数进行拟合,求出该函数的导数,并与理论推导结果进行比较。

f(x)=(x^2-3x+5)e^{-5x}sinx

解:

MATLAB代码如下:

  1. clc;clear;
  2. syms x;
  3. f=(x^2-3*x+5)*exp(-5*x)*sin(x);
  4. ezplot(diff(f),[0,1]) %理论结果
  5. hold on,
  6. x=0:.12:1;
  7. y=(x.^2-3*x+5).*exp(-5*x).*sin(x);
  8. sp1=csapi(x,y); %建立三次样条函数
  9. dsp1=fnder(sp1,1);
  10. fnplt(dsp1,'--'); %绘制样条图
  11. hold on,
  12. sp2=spapi(5,x,y); %5阶次B样条插值
  13. dsp2=fnder(sp2,1);
  14. fnplt(dsp2,':');
  15. axis([0,1,-0.8,5])

运行结果:

例题3

自行选择z=f(x,y)中的数据,来拟合\frac{\partial^2z}{\partial x\partial y}的曲面,并与解析解法绘制出的曲面相比较。

z=f(x,y)=(x^2-2x)e^{-x^2-y^2-xy}

解:

MATLAB代码如下:

  1. clc;clear;
  2. %拟合曲面
  3. x0=-3:.3:3;
  4. y0=-2:.2:2;
  5. [x,y]=ndgrid(x0,y0);
  6. z=(x.^2-2*x).*exp(-x.^2-y.^2-x.*y);
  7. sp=spapi({5,5},{x0,y0},z); %B样条
  8. dspxy=fnder(sp,[1,1]);
  9. fnplt(dspxy) %生成样条图
  10. %理论方法
  11. syms X Y;
  12. Z=(X^2-2*X)*exp(-X^2-Y^2-X*Y);
  13. figure;
  14. ezsurf(diff(diff(Z,X),Y),[-3 3],[-2 2])
  15. %对符号变量表达式做三维表面图

运行结果:

三. 基于样条插值的数值积分

S作为样条函数,对其进行数值积分格式如下:

f=fnint(S)

 例题4

考虑以下积分中较稀疏的样本点,用样条积分的方式求出定积分及积分函数。

\int_0^\pi sinxdx

解:

MATLAB函数如下:

  1. clc;clear;
  2. x=[0,0.4,1,2,pi];
  3. y=sin(x);
  4. %建立三次样条函数并积分
  5. sp1=csapi(x,y);
  6. a=fnint(sp1,1);
  7. xx1=fnval(a,[0,pi]);
  8. integral1=xx1(2)-xx1(1)
  9. %建立B样条函数并积分
  10. sp2=spapi(5,x,y);
  11. b=fnint(sp2,1);
  12. xx2=fnval(b,[0,pi]);
  13. integral2=xx2(2)-xx2(1)
  14. %绘制曲线
  15. ezplot('-cos(t)+2',[0,pi]); %不定积分可以上下平移
  16. hold on,
  17. fnplt(a,'--');
  18. fnplt(b,':');

运行结果:

四.分段多项式

根据间断数和系数生成分段多项式pp,每个系数的值都是长度为d的向量。MATLAB格式如下:

pp=mkpp(breaks,coefs,d)

可以使用ppval来计算特定点处的分段多项式,也可以使用unmkpp来提取有关分段多项式的详细信息。

例题5

创建任意一个分段多项式,使得它在区间[0,4]内具有三次多项式,在区间[4,10]内具有二次多项式,在区间[10,15]内具有四次多项式。

解:

MATLAB代码如下:

  1. clc;clear;
  2. breaks=[0 4 10 15];
  3. coefs=[0 1 -1 1 1;0 0 1 -2 53;-1 6 1 4 77]; %一共有三段
  4. pp=mkpp(breaks,coefs)
  5. %画图
  6. xq=0:0.01:15;
  7. plot(xq,ppval(pp,xq))
  8. line([4 4],ylim,'LineStyle','--','Color','k')
  9. line([10 10],ylim,'LineStyle','--','Color','k')

运行结果:

例题6

创建一个具有四个区间的单个分段多项式,这些区间在两个二次多项式之间交替。

解:

MATLAB代码如下:

  1. clc;clear;
  2. %显示一个二次多项式在[-8,-4]区间上的结果
  3. subplot(2,2,1)
  4. cc=[-1/4 1 0];
  5. pp1=mkpp([-8 -4],cc);
  6. xx1=-8:0.1:-4;
  7. plot(xx1,ppval(pp1,xx1),'k-')
  8. %在[-4,0]区间上的求反
  9. subplot(2,2,2)
  10. pp2=mkpp([-4 0],-cc);
  11. xx2=-4:0.1:0;
  12. plot(xx2,ppval(pp2,xx2),'k-')
  13. %将二次多项式扩展到四个区间形成的分段多项式
  14. %显示一阶导数,该导数利用unmkpp分解分段多项式构造而成
  15. subplot(2,1,2)
  16. pp=mkpp([-8 -4 0 4 8],[cc;-cc;cc;-cc]);
  17. xx=-8:0.1:8;
  18. plot(xx,ppval(pp,xx),'k-')
  19. [breaks,coefs,k,d]=unmkpp(pp);
  20. dpp=mkpp(breaks,repmat(k-1:-1:1,d*1,1).*coefs(:,1:k-1),d);

 运行结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/90302
推荐阅读
相关标签
  

闽ICP备14008679号