试求三次样条插值S(X)
- 格式:docx
- 大小:17.24 KB
- 文档页数:4
四、三次样条插值1. 样条函数插值的原理给定区间[a,b]上划分A:a=x<x<<x<x=b,若分段函数S(x)满足:01n-1n1.S(x)在各个子区间[x,x],i=0,1,,n-1上均为x的三次多项式;ii+12.S(x)在整个区间[a,b]上有直至二阶的连续导数。
则称S(x)为[a,b]上依次划分的三次样条函数,简称样条函数。
具体地有分段表达式:ax3+bx2+cx+d,x G[x,x]000001ax3+bx2+cx+d,x G[x,x]111112S(x)=\ax3+bx2+cx+d,x G[x,x](1)222223ax3+bx2+cx+d,x G[x,x]、°*n-1n—T•••n-1n-1n-1n共有4n个参数a,b,c,d,i=0,1,,n,它们在内节点处满足iiii'S(x)=S(x),…i-0i+0<S'(x)=S'(x),i=1,2,,n-1.(2)i-0i-0S''(x)=S''(x),Ji-0i+0满足样条函数定义的函数集合称为分划A上的三次样条函数空间,记为S(3,A),可以证明S(3,A)为线性空间。
若S(x)G S(3,A),且进一步满足插值条件S(x)=y=f(x),i=0,1,,n(3)iii其中y为节点x处的给定函数值(若被插函数了(x)已知;••则用了(x)代替之),iii则称S(x)为以x,x,,x,x为节点的三次样条函数。
01n-1n其中式(3)插值节点提供了n+1个约束条件;加上式(2)的3n-3个,合起来共有4n-2个;欲求4n个待定参数的唯一解;尚缺两个条件。
这两个条件一般由样条函数的边界条件提供。
常用三类边界条件;他们分别与三次样条函数;构成不同边界条件的样条函数插值问题。
2. 三类样条函数插值问题2.1第二类边界条件给定边界条件两端的一阶导数值:S'(x)=y'=m,S'(x)=y'=m000nnn这相当于样条两短处的方向给定(压铁在两端点的压力方向确定),对应的插值问题如下:对于分划A:a=x<x<<x<x=b,给定节点对应的函数值01n—1ny,y,y,,y,以及两端点处的一阶导数值y'=m,y'=m,求三次样条函数012n00nnS(x),使…f S(x)=y,i=0,1,,n2iiI S'(x)=m,S'(x)=mJ00n…n2.2第一类边界条件给定边界两端的二阶导数值:S''(x)=y''=M,S''(x)=y''=M000nnn这相当于在样条两端处外加一个力矩,使梁两端点处有相应的曲率。
问题1:20.给定数据如下表:试求三次样条插值S(x),并满足条件 (1)S`(0.25)=1.0000,S`(0.53)=0.6868; (2)S ’’(0.25)=S ’’(0.53)=0。
分析:本问题是已知五个点,由这五个点求一三次样条插值函数。
边界条件有两种,(1)是已知一阶倒数,(2)是已知自然边界条件。
对于第一种边界(已知边界的一阶倒数值),可写出下面的矩阵方程。
⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡=⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡432104321034322110d M M M M M 200020000020022d d d d λμμλμλμλ其中μj =j1-j 1-j h h h +,λi=j1-j j h h h +,dj=6f[x j-1,x j ,x j+1], μn =1,λ0=1对于第一种边界条件d 0=0h 6(f[x 0,x 1]-f 0`),d n =1-n h 6(f`n-f `[x n-1,x n ]) 解:由matlab 计算得:由此得矩阵形式的线性方程组为:⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎣⎡=⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎣⎡ 2.1150-2.4286-3.2667-4.3143-5.5200-M M M M M 25714.00001204286.000004000.026000.0006429.023571.0001243210解得 M 0=-2.0286;M 1=-1.4627;M 2= -1.0333; M 3= -0.8058; M 4=-0.6546S(x)=⎪⎪⎩⎪⎪⎨⎧∈-+-+-∈-+-+-∈-+-+-∈-+-+-]53.0,45.0[x 5.40x 9.1087x 35.03956.8.450-x 1.3637-x .5301.67881- ]45.0,39.0[x 9.30x 11.188x 54.010.418793.0-x 2.2384-x .450(2.87040-]39.0,30.0[x 03.0x 6.9544x 9.30 6.107503.0-x 1.9136-x .3902.708779-]30.0,25.0[x 5.20x 10.9662x 0.3010.01695.20-x 4.8758-x .3006.76209-33333333),()()()(),()()()),()()()(),()()()(Matlab 程序代码如下:function tgsanci(n,s,t) %n代表元素数,s,t代表端点的一阶导。
三次样条求离散点斜率的公式
我们要找出三次样条插值法中离散点斜率的计算公式。
首先,我们需要了解三次样条插值法的基本原理。
三次样条插值法是一种数学方法,用于通过给定的离散点集来拟合一个连续的函数。
这个方法的关键在于找到一个连续的、在离散点处可微的函数,这个函数通常被称为“样条”。
假设我们有一个离散点集(x0, y0), (x1, y1), ..., (xn, yn)。
我们希望找到一个连续的、在离散点处可微的函数S(x),使得S(xi) = yi,其中i = 0, 1, ..., n。
三次样条插值法的核心在于找到这样一个函数S(x),它由一系列的三次多项式组成,这些多项式在相邻的离散点之间是连续的,并且在离散点的边界处也是连续的。
对于离散点(xi, yi),其斜率可以通过以下公式计算:
斜率= 3hi / (xi - xi-1)
其中hi 是样条在该点处的“高度”(或称为“步长”)。
这个公式告诉我们如何根据给定的离散点集计算每个离散点的斜率。
计算结果为:斜率= 3hi / (xi - xi-1)
所以,离散点斜率的计算公式为:斜率= 3hi / (xi - xi-1)。
第四版数值分析习题第一章绪论设x>O,x 的相对误差为S ,求In x 的误差. 设x 的相对误差为2%,求x n 的相对误差. 下列各数都是经过四舍五入得到的近似数,即误差限不超过最后一位的半个单位 ,试指出它们是几位有效数字: x = 1.1021, x^ = 0.031, x^ = 385.6, x^ = 56.430, x^ = 7 1.0.利用公式(3.3)求下列各近似值的误差限:(i)x *+x ;+x 4,(ii)x *x ;x ;,(iii )x ;/x ;,其中 x ;,x ;,x 3,x ;均为第 3题所给的数.计算球体积要使相对误差限为 1%,问度量半径R 时允许的相对误差限是多少 ?设\)=28,按递推公式AY n =Y n d- _ .783100( n=1,2,…)计算到Y 00.若取7783衣27.982(五位有效数字),试问计算^00将有多大误差? 求方程X 2 -56X • 1 =0的两个根,使它至少具有四位有效数字 (■ 783沁27.982).\ ------ d x 当N 充分大时,怎样求N 1 x? 正方形的边长大约为 100 cm ,应怎样测量才能使其面积误差不超过 s *2设 2 假定g 是准确的,而对t 的测量有土 0.1秒的误差,证明当t 增加时s 的绝对 误差增加,而相对误差却减小. 序列{yn}满足递推关系y n _ 10y n _ 1(n=1,2,…),若y0 _ X 2 1.41 (三位有效数字),计算到y 10时误差有多大?这个计算过程稳定吗?计算f = c- 2 一1)6,取' 2 : 1.4,利用下列等式计算,哪一个得到的结果最好?f (x) =1 n (x X -1),求 f(30)的值.若开平方用六位函数表,问求对数时误差有多大改用另一等价公式ln(x_ Jx 2 T) = -ln(x +Jx 2 +1)计算,求对数时误差有多大?1. 2. 3. 4.5. 6.7.8.9.10.11.12.13.21 cm1 (、2 1)61 (32 . 2)3,99 -70、2.?若根据(2.2)定义的范德蒙行列式,令证明V n (x)是n 次多项式,它的根是X 0^L ,X nJ ,且当x= 1 , -1 , 2时,f(x)= 0 , -3,4 ,求f(x)的二次插值多项式.给出cos x,0 ° < x 90。
/* 三次样条插值计算算法*/#include "math.h "#include "stdio.h "#include "stdlib.h "/*N:已知节点数N+1R:欲求插值点数R+1x,y为给定函数f(x)的节点值{x(i)} (x(i) <x(i+1)) ,以及相应的函数值{f(i)} 0 <=i <=NP0=f(x0)的二阶导数;Pn=f(xn)的二阶导数u:存插值点{u(i)} 0 <=i <=R求得的结果s(ui)放入s[R+1] 0 <=i <=R返回0表示成功,1表示失败*/int SPL(int N,int R,double x[],double y[],double P0,double Pn,double u[],double s[]){/*声明局部变量*/double *h; /*存放步长:{hi} 0 <=i <=N-1 */double *a; /*存放系数矩阵{ai} 1 <=i <=N ;分量0没有利用*/ double *c; /*先存放系数矩阵{ci} 后存放{Bi} 0 <=i <=N-1 */double *g; /*先存放方程组右端项{gi} 后存放求解中间结果{yi} 0 <=i <=N */double *af; /*存放系数矩阵{a(f)i} 1 <=i <=N ;*/double *ba; /*存放中间结果0 <=i <=N-1*/double *m; /*存放方程组的解{m(i)} 0 <=i <=N ;*/int i,k;double p1,p2,p3,p4;/*分配空间*/if(!(h=(double*)malloc(N*sizeof(double)))) exit(1);if(!(a=(double*)malloc((N+1)*sizeof(double)))) exit(1);if(!(c=(double*)malloc(N*sizeof(double)))) exit(1);if(!(g=(double*)malloc((N+1)*sizeof(double)))) exit(1);if(!(af=(double*)malloc((N+1)*sizeof(double)))) exit(1);if(!(ba=(double*)malloc((N)*sizeof(double)))) exit(1);if(!(m=(double*)malloc((N+1)*sizeof(double)))) exit(1);/*第一步:计算方程组的系数*/for(k=0;k <N;k++)h[k]=x[k+1]-x[k];for(k=1;k <N;k++)a[k]=h[k]/(h[k]+h[k-1]);for(k=1;k <N;k++)c[k]=1-a[k];for(k=1;k <N;k++)g[k]=3*(c[k]*(y[k+1]-y[k])/h[k]+a[k]*(y[k]-y[k-1])/h[k-1]); c[0]=a[N]=1;g[0]=3*(y[1]-y[0])/h[0]-P0*h[0]/2;g[N]=3*(y[N]-y[N-1])/h[N-1]+Pn*h[N-1]/2;/*第二步:用追赶法解方程组求{m(i)} */ba[0]=c[0]/2;g[0]=g[0]/2;for(i=1;i <N;i++){af[i]=2-a[i]*ba[i-1];g[i]=(g[i]-a[i]*g[i-1])/af[i];ba[i]=c[i]/af[i];}af[N]=2-a[N]*ba[N-1];g[N]=(g[N]-a[N]*g[N-1])/af[N];m[N]=g[N]; /*P110 公式:6.32*/ for(i=N-1;i> =0;i--)m[i]=g[i]-ba[i]*m[i+1];/*第三步:求值*/for(i=0;i <=R;i++){/*判断u(i)属于哪一个子区间,即确定k */if(u[i] <x[0] || u[i]> x[N]){/*释放空间*/free(h);free(a);free(c);free(g);free(af);free(ba);free(m);return 1;}k=0;while(u[i]> x[k+1])k++;//p1=(h[k]+2*(u[i]-x[k])*pow((u[i]-x[k+1]),2)*y[k])/pow(h[k],3); //p2=(h[k]-2*(u[i]-x[k+1])*pow((u[i]-x[k]),2)*y[k+1])/pow(h[k],3);p1=(h[k]+2*(u[i]-x[k]))*pow((u[i]-x[k+1]),2)*y[k]/pow(h[k],3);p2=(h[k]-2*(u[i]-x[k+1]))*pow((u[i]-x[k]),2)*y[k+1]/pow(h[k],3); p3=(u[i]-x[k])*pow((u[i]-x[k+1]),2)*m[k]/pow(h[k],2);p4=(u[i]-x[k+1])*pow((u[i]-x[k]),2)*m[k+1]/pow(h[k],2);s[i]=p1+p2+p3+p4;}/*释放空间*/free(h);free(a);free(c);free(g);free(af);free(ba);free(m);return 0;}void main(){int N,R;double *x,*y,*u,*s;double P0,Pn;int i;/*验证算法:*/N=7;R=6;/*分配空间*/if(!(x=(double*)malloc((N+1)*sizeof(double)))){printf( "malloc error!\n ");exit(1);}if(!(y=(double*)malloc((N+1)*sizeof(double)))){printf( "malloc error!\n ");exit(1);}if(!(u=(double*)malloc((R+1)*sizeof(double)))){printf( "malloc error!\n ");exit(1);}if(!(s=(double*)malloc((R+1)*sizeof(double)))){printf( "malloc error!\n ");exit(1);}x[0]=0.5;x[1]=0.7;x[2]=0.9;x[3]=1.1;x[4]=1.3;x[5]=1.5;x[6]=1.7;x[7]=1.9;y[0]=0.4794;y[1]=0.6442;y[2]=0.7833;y[3]=0.8912;y[4]=0.9636;y[5]=0.9975;y[6]=0.9917;y[7]=0.9 463;u[0]=0.6;u[1]=0.8;u[2]=1.0;u[3]=1.2;u[4]=1.4;u[5]=1.6;u[6]=1.8;P0=-0.4794;Pn=-0.9463;if(!SPL( N, R, x, y, P0, Pn, u, s)){/*打印结果*/printf( "\nx= ");for(i=0;i <=N;i++)printf( "%8.1f ",x[i]);printf( "\ny= ");for(i=0;i <=N;i++)printf( "%8.4f ",y[i]);printf( "\n\nu= ");for(i=0;i <=R;i++)printf( "%9.2f ",u[i]);printf( "\ns= ");for(i=0;i <=R;i++)printf( "%9.5f ",s[i]);printf( "\nsin= ");for(i=0;i <=R;i++)printf( "%9.5f ",sin(u[i]));}/*释放空间*/free(x);free(y);free(u);free(s);}/* 测试数据来自课本55页例5 《数值分析》清华大学出版社第四版*/ //输入327.7 4.128 4.329 4.130 3.013.0 -4.0//输出输出三次样条插值函数:1: [27.7 , 28]13.07*(x - 28)^3 + 0.22*(x - 27.7)^3+ 14.84*(28 - x) + 14.31*(x - 27.7)2: [28 , 29]0.066*(29 - x)^3 + 0.1383*(x - 28)^3+ 4.234*(29 - x) + 3.962*(x - 28)3: [29 , 30]0.1383*(30 - x)^3 - 1.519*(x - 29)^3+ 3.962*(30 - x) + 4.519*(x - 29)//三次样条插值函数#include<iostream>#include<iomanip>using namespace std;const int MAX = 50;float x[MAX], y[MAX], h[MAX];float c[MAX], a[MAX], fxym[MAX];float f(int x1, int x2, int x3){float a = (y[x3] - y[x2]) / (x[x3] - x[x2]);float b = (y[x2] - y[x1]) / (x[x2] - x[x1]);return (a - b)/(x[x3] - x[x1]);} //求差分void cal_m(int n){ //用追赶法求解出弯矩向量M……float B[MAX];B[0] = c[0] / 2;for(int i = 1; i < n; i++)B[i] = c[i] / (2 - a[i]*B[i-1]);fxym[0] = fxym[0] / 2;for(i = 1; i <= n; i++)fxym[i] = (fxym[i] - a[i]*fxym[i-1]) / (2 - a[i]*B[i-1]);for(i = n-1; i >= 0; i--)fxym[i] = fxym[i] - B[i]*fxym[i+1];}void printout(int n);int main(){int n,i; char ch;do{cout<<"Please put in the number of the dots:";cin>>n;for(i = 0; i <= n; i++){cout<<"Please put in X"<<i<<':';cin>>x[i]; //cout<<endl;cout<<"Please put in Y"<<i<<':';cin>>y[i]; //cout<<endl;}for(i = 0; i < n; i++) //求步长h[i] = x[i+1] - x[i];cout<<"Please 输入边界条件\n 1: 已知两端的一阶导数\n 2:两端的二阶导数已知\n 默认:自然边界条件\n";int t;float f0, f1;cin>>t;switch(t){case 1:cout<<"Please put in Y0\' Y"<<n<<"\'\n";cin>>f0>>f1;c[0] = 1; a[n] = 1;fxym[0] = 6*((y[1] - y[0]) / (x[1] - x[0]) - f0) / h[0];fxym[n] = 6*(f1 - (y[n] - y[n-1]) / (x[n] - x[n-1])) / h[n-1];break;case 2:cout<<"Please put in Y0\" Y"<<n<<"\"\n";cin>>f0>>f1;c[0] = a[n] = 0;fxym[0] = 2*f0; fxym[n] = 2*f1;break;default:cout<<"不可用\n";//待定};//switchfor(i = 1; i < n; i++)fxym[i] = 6 * f(i-1, i, i+1);for(i = 1; i < n; i++){a[i] = h[i-1] / (h[i] + h[i-1]);c[i] = 1 - a[i];}a[n] = h[n-1] / (h[n-1] + h[n]);cal_m(n);cout<<"\n输出三次样条插值函数:\n";printout(n);cout<<"Do you to have anther try ? y/n :";cin>>ch;}while(ch == 'y' || ch == 'Y');return 0;}void printout(int n){cout<<setprecision(6);for(int i = 0; i < n; i++){cout<<i+1<<": ["<<x[i]<<" , "<<x[i+1]<<"]\n"<<"\t";/*cout<<fxym[i]/(6*h[i])<<" * ("<<x[i+1]<<" - x)^3 + "<<<<" * (x - "<<x[i]<<")^3 + "<<(y[i] - fxym[i]*h[i]*h[i]/6)/h[i]<<" * ("<<x[i+1]<<" - x) + "<<(y[i+1] - fxym[i+1]*h[i]*h[i]/6)/h[i]<<"(x - "<<x[i]<<")\n";cout<<endl;*/float t = fxym[i]/(6*h[i]);if(t > 0)cout<<t<<"*("<<x[i+1]<<" - x)^3";else cout<<-t<<"*(x - "<<x[i+1]<<")^3";t = fxym[i+1]/(6*h[i]);if(t > 0)cout<<" + "<<t<<"*(x - "<<x[i]<<")^3";else cout<<" - "<<-t<<"*(x - "<<x[i]<<")^3";cout<<"\n\t";t = (y[i] - fxym[i]*h[i]*h[i]/6)/h[i];if(t > 0)cout<<"+ "<<t<<"*("<<x[i+1]<<" - x)";else cout<<"- "<<-t<<"*("<<x[i+1]<<" - x)";t = (y[i+1] - fxym[i+1]*h[i]*h[i]/6)/h[i];if(t > 0)cout<<" + "<<t<<"*(x - "<<x[i]<<")";else cout<<" - "<<-t<<"*(x - "<<x[i]<<")";cout<<endl<<endl;}cout<<endl;}。
三次样条曲线表达式:灵活优美的曲线绘制方式在计算机图形学、数值计算和信号处理等领域中,数字化的连续函数是非常重要的一种形式。
而曲线是这种函数形式中的一个最基本的形式,可以被广泛地应用在计算机图形学、几何建模、视觉处理等方面。
而三次样条曲线就是其中一种非常灵活优美的曲线绘制方式。
三次样条曲线是将一段数据区间上的数据点插值得到的平滑曲线,其中“三次样条”的名称来自于插值函数的阶数和一种类似于自然样条函数的方式。
插值函数在每个插值点上都有一个有限的导数,因此在这些点之间不能出现任何角或拐点。
而且,由于样条插值函数比全局多项式插值函数具有更低的阶数,因此这种方法能够防止烦人的振荡现象。
三次样条曲线曲线绘制的基本思想是利用一个三次多项式来连接相邻的数据点。
该多项式的系数由这些点的值和导数决定,且利用相邻点间的差分来解出这些系数。
这样,曲线就可以平滑地穿过数据点,同时保持足够的灵活性,以便能够在不同的数据点之间呈现出各种优美的曲线。
一个三次样条曲线可以写成如下形式:S(x) = Si(x), xi ≤ x ≤ xi+1其中,i表示插值点之间的段数,xi是第i个插值点的x坐标,Si是第i个样条段的函数。
在插值点处,三次样条曲线具有相同的函数值和导数,即:Si(xi) = y[i],即第i个段的起点函数值等于第i个插值点的函数值Si(xi+1) = y[i+1],即第i个段的终点函数值等于第i+1个插值点的函数值Si'(xi) = d[i],即第i个段的起点导数等于第i个插值点的导数Si'(xi+1) = d[i+1],即第i个段的终点导数等于第i+1个插值点的导数而在插值点之间的点处,三次样条曲线的函数值和导数是由相邻两个插值点之间的三次多项式决定的。
也就是说,插值点之间的段数越多,函数值和导数的变化就越平滑,曲线就越优美。
利用三次样条曲线的灵活性,我们可以将其应用于如下场景中:1.计算机图形学:三次样条曲线在计算机图形学方面的应用非常广泛,它可以被用于绘制三维曲面的边缘、建立多边形曲线、创建复杂的动画效果等。
三次样条插值的求解摘要:分段低次插值虽然解决了高次插值的振荡现象和数值不稳定现象,使得插值多项式具有一致收敛性,保证了插值函数整体的连续性,但在函数插值节点处不能很好地保证光滑性要求,这在某些要求光滑性的工程应用中是不能接受的。
如飞机的机翼一般要求使用流线形设计,以减少空气阻力,还有船体放样等的型值线,往往要求有二阶光滑度(即有二阶连续导数)。
因此,在分段插值的基础上,引进了一种新的插值方法,在保证原方法的收敛性和稳定性的同时,又使得函数具有较高的光滑性的样条插值。
关键字:三转角方程 三弯矩阵方程0. 引言1,三次样条函数定义1:若函数2()[,]S x a b C ∈,且在每个小区间上1,j j x x +⎡⎤⎦⎣上是三次多项式,其中01n a x x x b ⋯=<<<= 是给定节点,则称()s x 是节点01,,,n x x x ⋯上的三次样条函数。
若节点j x 上 给定函数值()j j y f x =(0,1,)j n ⋯= ,且()j j s x y = (0,1,)j n ⋯= (1.1)成立,则称 ()s x 为三次样条差值函数。
从定义知,要求出()s x ,在每个应小区间1[,]j j x x + 上确定4个待定系数,共有 n 个小区间,故应确定4n 个参数,根据()s x 在[,]a b 上二阶导数连续,在节点()1,2,3,,1j x j n ⋯=-处应满足连续性条件(0)(0),j j s x s x -=+ ''(0)(0),j j s x s x -=+''''(0)(0)j j s x s x -=+ (1.2) 共有 3n-3个条件,再加上()s x 满足插值条件(1.1),共有4n-2个条件,因此还需要2个条件才能确定()s x 。
通常可在区间[,]a b 端点0,n a x b x ==上各加一个条件(称边界条件),边界条件可根据实际的问题要求给定。
例1 设)(x f 为定义在[0,3]上的函数,有下列函数值表:且2.0)('0=x f ,1)('3-=x f ,试求区间[0,3]上满足上述条件的三次样条插值函数)(x s本算法求解出的三次样条插值函数将写成三弯矩方程的形式:)()6()()6()(6)(6)(211123131j j jj j j jj j j j jj j jj x x h h M y x x h h M y x x h M x x h M x s --+--+-+-=+++++其中,方程中的系数jj h M 6,jj h M 61+,jj j j h h M y )6(2-,jjj j h h M y )6(211++-将由Matlab代码中的变量Coefs_1、Coefs_2、Coefs_3以及Coefs_4的值求出。
以下为Matlab 代码:%=============================% 本段代码解决作业题的例1%============================= clear all clc% 自变量x 与因变量y ,两个边界条件的取值 IndVar = [0, 1, 2, 3]; DepVar = [0, 0.5, 2, 1.5];LeftBoun = 0.2; RightBoun = -1;% 区间长度向量,其各元素为自变量各段的长度 h = zeros(1, length(IndVar) - 1); for i = 1 : length(IndVar) - 1h(i) = IndVar(i + 1) - IndVar(i); end% 为向量μ赋值mu = zeros(1, length(h));for i = 1 : length(mu) - 1mu(i) = h(i) / (h(i) + h(i + 1));endmu(i + 1) = 1;% 为向量λ赋值lambda = zeros(1, length(h));lambda(1) = 1;for i = 2 : length(lambda)lambda(i) = h(i) / (h(i - 1) + h(i));end% 为向量d赋值d = zeros(1, length(h) + 1);d(1) = 6 * ( (DepV ar(2) - DepVar(1) ) / ( IndVar(2) - IndVar(1) ) - LeftBoun) / h(1);for i = 2 : length(h)a = ( DepVar(i) - DepVar(i - 1) ) / ( IndVar(i) - IndVar(i - 1) );b = ( DepVar(i + 1) - DepVar(i) ) / ( IndVar(i + 1) - IndVar(i) );c = (b - a) / ( IndVar(i + 1) - IndVar(i - 1) );d(i) = 6 * c;endd(i + 1) = 6 *( RightBoun - ( DepVar(i + 1) - DepVar(i) ) / ( IndVar(i + 1) - IndVar(i) ) ) / h(i);% 为矩阵A赋值% 将主对角线上的元素全部置为2A = zeros( length(d), length(d) );for i = 1 : length(d)A(i, i) = 2;end% 将向量λ的各元素赋给主对角线右侧第一条对角线for i = 1 : length(d) - 1A(i, i + 1) = lambda(i);end% 将向量d的各元素赋给主对角线左侧第一条对角线for i = 1 : length(d) - 1A(i + 1, i) = mu(i);end% 求解向量MM =A \ d';% 求解每一段曲线的函数表达式for i = 1 : length(h)Coefs_1 = M(i) / (6 * h(i));Part_1 = conv( Coefs_1, ...conv( [-1, IndVar(i + 1)], ...conv( [-1, IndVar(i + 1)], [-1, IndVar(i + 1)] ) ) );S_1 = polyval (Part_1, [IndVar(i) : 0.01 : IndVar(i + 1)]);Coefs_2 = M(i + 1)/(6 * h(i));Part_2 = conv( Coefs_2, ...conv( [1, -IndVar(i)], ...conv( [1, -IndVar(i)], [1, -IndVar(i)] ) ) );S_2 = polyval (Part_2, [IndVar(i) : 0.01 : IndVar(i + 1)]);Coefs_3 = (DepVar(i) - M(i) * h(i)^2 / 6) / h(i);Part_3 = conv(Coefs_3, [-1, IndVar(i + 1)]);S_3 = polyval (Part_3, [IndVar(i) : 0.01 : IndVar(i + 1)]);Coefs_4 = (DepVar(i + 1) - M(i + 1) * h(i)^2 / 6) / h(i);Part_4 = conv(Coefs_4, [1, -IndVar(i)]);S_4 = polyval (Part_4, [IndVar(i) : 0.01 : IndVar(i + 1)]);S = S_1 + S_2 + S_3 + S_4;plot ([IndVar(i) : 0.01 : IndVar(i + 1)], S, 'LineWidth', 1.25)% 在样条插值曲线的相应位置标注该段曲线的函数表达式text(i - 1, polyval(Part_1, 3), ...['\itS', num2str(i), '(x)=', num2str(Coefs_1), '(', num2str( IndVar(i + 1) ), '-x)^{3}+', ...num2str(Coefs_2), '(x-', num2str( IndVar(i) ), ')^{3}+', num2str(Coefs_3), ...'(', num2str( IndVar(i + 1) ), '-x)+', num2str(Coefs_4), '(x-', num2str( IndVar(i) ), ')'], ...'FontName', 'Times New Roman', 'FontSize', 14)hold onend% 过x=1和x=2两个横轴点作垂线%line([1, 1], [2.5, -0.5], 'LineStyle', '--');line([2, 2], [2.5, -0.5], 'LineStyle', '--');% 为x轴和y轴添加标注xlabel( '\itx', 'FontName', 'Times New Roman', ...'FontSize', 14, 'FontWeight', 'bold');ylabel( '\its(x)', 'FontName', 'Times New Roman', ...'Rotation', 0, 'FontSize', 14, 'FontWeight', 'bold');最终,三次样条插值函数s(x)表达式为:[][][]⎪⎩⎪⎨⎧∈-+-+-+--∈-+-+---∈+-++--=.3,2,)2(44.1)3(62.2)2(06.0)3(62.0,2,1,)1(62.2)2(08.0)1(62.0)2(42.0,1,0,08.0)1(06.042.0)1(06.0)(333333x x x x x x x x x x x x x x x x s曲线的图像如图所示:例2 已知函数值表:试求在区间[1,5]上满足上述函数表所给出的插值条件的三次自然样条插值函数)(x s本算法求解出的三次样条插值函数将写成三弯矩方程的形式:)()6()()6()(6)(6)(211123131j j jj j j jj j j j jj j jj x x h h M y x x h h M y x x h M x x h M x s --+--+-+-=+++++其中,方程中的系数jj h M 6,jj h M 61+,jj j j h h M y )6(2-,jjj j h h M y )6(211++-将由Matlab代码中的变量Coefs_1、Coefs_2、Coefs_3以及Coefs_4的值求出。
实验一拉格朗日插值、分段线性插值、三次样条插值的比较一、问题提出选择函数y=exp(-x2) (-2≤x≤2),在n个节点上(n不要太大,如5~11)用拉格朗日、分段线性、三次样条三种插值方法,计算m个插值点的函数值(m要适中,如50~100)。
二、要求通过数值和图形输出,将三种插值结果与精确值进行比较。
适当增加n,在作比较,由此作初步分析。
三、问题的解答为统一起见,认为题目中的节点指的是中间节点,插值时还要考虑两端点的函数值,故原题目中有 n+2 个插值节点。
以下给出题目所需的 MATLAB 函数,其中参数 count_knot 表示题目中的n ,count_dot 表示题目中的m 。
function result=campare3inter(count_knot,count_dot)%count_knot 中间节点的个数%count_dot 拟合的函数值的个数clfknot=linspace(-2,2,count_knot+2);x=-2:0.01:2;y=exp(-x.^2);y0=exp(-knot.^2);plot(x,y,knot,y0,'ro');%,hold on;x_new=linspace(-2,2,count_dot);y_real=exp(-x_new.^2);%Lagrange 插值y_lagrange=lagrange(knot,y0,x_new);plot(x_new,y_lagrange,'k');hold on;%分段线性插值y_line=zeros(1,length(x_new))count_1=1;for j=1:count_dotfor i=1:count_knot+1if((x_new(j)>=knot(i))&((x_new(j)<=knot(i+1))))%直线的点斜式方程y_line(count_1)=((y0(i)-y0(i+1))/(knot(i)-knot(i+1)))*(x_new(j)-knot(i))+y0(i);count_1=count_1+1;break;end endendplot(x_new,y_line,'b');hold on;%三次样条插值 y_temp=[0 y0 0];pp=csape(knot,y_temp,'second');[breaks,coefs,npolys,ncoefs,dim]=unmkpp(pp);count=1;for j=1:count_dotfor i=1:count_knot+1if((x_new(j)>=knot(i))&((x_new(j)<=knot(i+1))))y_spline(count)=polyval(coefs(i,:),x_new(j)-knot(i));count=count+1;break;end endendplot(x_new,y_spline,'g');%输出原函数值和三种插值函数值的比较结果result=[y_real' y_lagrange' y_line' y_spline']图形输出(n=5,m=50)10.90.80.70.60.50.40.30.20.1-2 -1.5 -1 -0.5 0 0.5 1 1.5 2绿色:节点和exp(-x2)。