数值分析学习笔记——三次样条插值

2.6 三次样条插值

1.三次样条函数

(1)定义:若函数 S ( x ) ∈ C 2 [ a , b ] S(x)\in C^2[a,b] S(x)C2[a,b],且每个小区间 [ x j , x j + 1 ] [x_j,x_{j+1}] [xj,xj+1]上为三次多项式,其中 a = x 0 < x 1 < ⋯ < x n = b a=x_0<x_1<\cdots<x_n=b a=x0<x1<<xn=b为给定节点,则称 S ( x ) S(x) S(x)为节点 x 0 , x 1 , ⋯   , x n x_0,x_1,\cdots,x_n x0,x1,,xn三次样条函数

​ 若在节点 x j x_j xj上给定函数值 y j = f ( x j ) ( j = 0 , 1 , ⋯   , n ) y_j=f(x_j)(j=0,1,\cdots,n) yj=f(xj)(j=0,1,,n)并满足
S ( x j ) = y j , j = 0 , 1 , ⋯   , n (1.46) S(x_j)=y_j,j=0,1,\cdots,n\tag{1.46} S(xj)=yj,j=0,1,,n(1.46)
S ( x ) S(x) S(x)三次样条插值函数

(2)定值条件:要求 S ( x ) S(x) S(x),在每个小区间 [ x j , x j + 1 ] [x_j,x_{j+1}] [xj,xj+1]上要确定4个待定系数,共有 n n n个区间,故应确定 4 n 4n 4n个参数。根据 S ( x ) S(x) S(x) [ a , b ] [a,b] [a,b]上二阶导数连续,在节点 x j ( j = 1 , 2 , ⋯   , n − 1 ) x_j(j=1,2,\cdots,n-1) xj(j=1,2,,n1)满足连续性条件
S ( x j − 0 ) = S ( x j + 0 ) , S ′ ( x j − 0 ) = S ′ ( x j + 0 ) , S ′ ′ ( x j − 0 ) = S ′ ′ ( x j + 0 ) (1.47) S(x_j-0)=S(x_j+0),S^\prime(x_j-0)=S^\prime(x_j+0),S^{\prime\prime}(x_j-0)=S^{\prime\prime}(x_j+0)\tag{1.47} S(xj0)=S(xj+0),S(xj0)=S(xj+0),S′′(xj0)=S′′(xj+0)(1.47)
这里共有 3 n − 3 3n-3 3n3个条件,加上 S ( x ) S(x) S(x)满足(1.46)这 n + 1 n+1 n+1个条件,再加上边界条件区间 [ a , b ] [a,b] [a,b]左右端点 a = x 0 , b = x n a=x_0,b=x_n a=x0,b=xn,刚好满足 4 n 4n 4n个条件,三次样条函数问题可解,边界条件的三种常见情况:

​ 1)已知区间两端的一阶导数值,即
S ′ ( x 0 ) = f 0 ′ , S ′ ( x n ) = f n ′ (1.48) S^\prime(x_0)=f^\prime_0,S^\prime(x_n)=f^\prime_n \tag{1.48} S(x0)=f0,S(xn)=fn(1.48)
​ 2)已知区间两端的二阶导数值,即
S ′ ′ ( x 0 ) = f 0 ′ ′ , S ′ ′ ( x n ) = f n ′ ′ (1.49) S^{\prime\prime}(x_0)=f^{\prime\prime}_0,S^{\prime\prime}(x_n)=f^{\prime\prime}_n \tag{1.49} S′′(x0)=f0′′,S′′(xn)=fn′′(1.49)
​ 特殊情况(自然边界条件
S ′ ′ ( x 0 ) = S ′ ′ ( x n ) = 0 (1.49-C) S^{\prime\prime}(x_0)=S^{\prime\prime}(x_n)=0 \tag{1.49-C} S′′(x0)=S′′(xn)=0(1.49-C)
​ 3)当 f ( x ) f(x) f(x) x n − x 0 x_n-x_0 xnx0为周期的周期函数时,则要求 S ( x ) S(x) S(x)也是周期函数,满足
{ S ( x 0 + 0 ) = S ( x n − 0 ) , S ′ ( x 0 + 0 ) = S ′ ( x n − 0 ) S ′ ′ ( x 0 + 0 ) = S ′ ′ ( x n − 0 ) (1.50) \begin{cases} S(x_0+0)=S(x_n-0),S^\prime(x_0+0)=S^\prime(x_n-0)\\ S^{\prime\prime}(x_0+0)=S^{\prime\prime}(x_n-0) \end{cases}\tag{1.50} {S(x0+0)=S(xn0),S(x0+0)=S(xn0)S′′(x0+0)=S′′(xn0)(1.50)
​ 此时满足(1.46)式中的 y 0 = y n y_0=y_n y0=yn,称这类样条函数 S ( x ) S(x) S(x)周期样条函数

2.三次样条插值函数

推导建立插值函数的过程:

​ 由二阶导数值 S ′ ′ ( x j ) = M j , j = 0 , 1 , ⋯   , n S^{\prime\prime}(x_j)=M_j,j=0,1,\cdots,n S′′(xj)=Mj,j=0,1,,n表达 S ( x ) S(x) S(x).由 S ( x ) S(x) S(x)在区间 [ x j , x j + 1 ] [x_j,x_{j+1}] [xj,xj+1]为三次多项式得 S ′ ′ ( x ) S^{\prime\prime}(x) S′′(x)为线性函数,写为
S ′ ′ ( x ) = M j x j + 1 − x h j + M j + 1 x − x j h j (1.51) S^{\prime\prime}(x)=M_j\frac{x_{j+1}-x}{h_j}+M_{j+1}\frac{x-x_j}{h_j}\tag{1.51} S′′(x)=Mjhjxj+1x+Mj+1hjxxj(1.51)
S ( x ) S(x) S(x)进行积分并利用 S ( x j ) = y j , S ( x j + 1 ) = y j + 1 S(x_j)=y_j,S(x_{j+1})=y_{j+1} S(xj)=yj,S(xj+1)=yj+1条件得到三次样条表达式
S ( x ) = M j ( x j + 1 − x ) 3 6 h j + M j + 1 ( x − x j ) 3 6 h j + ( y j − M j h j 2 6 ) x j + 1 − x h j + ( y j + 1 − M j + 1 h j 2 6 ) x − x j h j , j = 0 , 1 , ⋯   , n − 1 (1.52) S(x)=M_j\frac{(x_{j+1}-x)^3}{6h_j}+M_{j+1}\frac{(x-x_j)^3}{6h_j}+(y_j-\frac{M_jh_j^2}{6})\frac{x_{j+1}-x}{h_j}\\+(y_{j+1}-\frac{M_{j+1}h_j^2}{6})\frac{x-x_j}{h_j},j=0,1,\cdots,n-1\tag{1.52} S(x)=Mj6hj(xj+1x)3+Mj+16hj(xxj)3+(yj6Mjhj2)hjxj+1x+(yj+16Mj+1hj2)hjxxj,j=0,1,,n1(1.52)
求导得
S ′ ( x ) = − M j ( x j + 1 − x ) 2 2 h j + M j + 1 ( x − x j ) 2 2 h j + y j + 1 − y j 2 h j − M j + 1 − M j 6 h j (1.53) S^\prime(x)=-M_j\frac{(x_{j+1}-x)^2}{2h_j}+M_{j+1}\frac{(x-x_{j})^2}{2h_j}+\frac{y_{j+1}-y_j}{2h_j}-\frac{M_{j+1}-M_j}{6}h_j\tag{1.53} S(x)=Mj2hj(xj+1x)2+Mj+12hj(xxj)2+2hjyj+1yj6Mj+1Mjhj(1.53)
由此得到
S ′ ( x j + 0 ) = − h j 3 M j − h j 6 M j + 1 + y j + 1 − y j h j S ′ ( x j − 0 ) = h j − 1 6 M j − 1 + h j − 1 3 M j + y j − y j − 1 h j − 1 \begin{aligned}S^\prime(x_j+0)&=-\frac{h_j}{3}M_j-\frac{h_j}{6}M_{j+1}+\frac{y_{j+1}-y_{j}}{h_j}\\S^\prime(x_j-0)&=\frac{h_{j-1}}{6}M_{j-1}+\frac{h_{j-1}}{3}M_j+\frac{y_j-y_{j-1}}{h_{j-1}}\end{aligned} S(xj+0)S(xj0)=3hjMj6hjMj+1+hjyj+1yj=6hj1Mj1+3hj1Mj+hj1yjyj1
S ′ ( x j − 0 ) = S ′ ( x j + 0 ) S^\prime(x_j-0)=S^\prime(x_j+0) S(xj0)=S(xj+0)
μ j M j − 1 + 2 M j + λ j M j + 1 = d j , j = 1 , 2 , ⋯   , n − 1 (1.54) \mu_jM_{j-1}+2M_j+\lambda_jM_{j+1}=d_j,j=1,2,\cdots,n-1\tag{1.54} μjMj1+2Mj+λjMj+1=dj,j=1,2,,n1(1.54)
其中
μ j = h j − 1 h j − 1 + h j , λ j = h j h j − 1 + h j d j = 6 h j − 1 + h j ( f [ x j , x j + 1 ] − f [ x j , x j − 1 ] ) = f [ x j − 1 , x j , x j + 1 ] , j = 1 , 2 , ⋯   , n − 1 (1.55) \begin{aligned} \mu_j&=\frac{h_{j-1}}{h_{j-1}+h_j},\lambda_j=\frac{h_{j}}{h_{j-1}+h_j}\\d_j&=\frac{6}{h_{j-1}+h_j}(f[x_j,x_{j+1}]-f[x_j,x_{j-1}])=f[x_{j-1},x_j,x_{j+1}],j=1,2,\cdots,n-1 \end{aligned}\tag{1.55} μjdj=hj1+hjhj1,λj=hj1+hjhj=hj1+hj6(f[xj,xj+1]f[xj,xj1])=f[xj1,xj,xj+1],j=1,2,,n1(1.55)
最后再代入边界条件即可得到矩阵形式的方程组,解出 M k ( k = j − 1 , j , j + 1 ) M_k(k=j-1,j,j+1) Mk(k=j1,j,j+1)即可得到三次样条插值函数 S ( x ) S(x) S(x)​的表达式.

比较常见的是第一类边界条件的运用,将(1.48)式代入(1.53)式可以推出两个方程
2 M 0 + M 1 = 6 h 0 ( f [ x 0 , x 1 ] − f 0 ′ ) M n − 1 + 2 M n = 6 h n − 1 ( f n ′ − f [ x n − 1 , x n ] ) } (1.56) \begin{rcases} 2M_0+M_1=\frac{6}{h_0}(f[x_0,x_1]-f_0^\prime)\\ M_{n-1}+2M_n=\frac{6}{h_{n-1}}(f_n^\prime-f[x_{n-1},x_n]) \end{rcases}\tag{1.56} 2M0+M1=h06(f[x0,x1]f0)Mn1+2Mn=hn16(fnf[xn1,xn])}(1.56)
若令
λ 0 = 1 ; d 0 = 6 h 0 ( f [ x 0 , x 1 ] − f 0 ′ ) = 6 h 0 ( f [ x 0 , x 1 ] − P 0 ′ ) ; μ n = 1 ; d n = 6 h n − 1 ( f n ′ − f [ x n − 1 , x n ] ) = 6 h n − 1 ( P n ′ − f [ x n − 1 , x n ] ) . \begin{aligned} \lambda_0&=1;\\ d_0&=\frac{6}{h_0}(f[x_0,x_1]-f_0^\prime)=\frac{6}{h_0}(f[x_0,x_1]-P_0^\prime);\\ \mu_n&=1;\\ d_n&=\frac{6}{h_{n-1}}(f_n^\prime-f[x_{n-1},x_n])=\frac{6}{h_{n-1}}(P_n^\prime-f[x_{n-1},x_n]). \end{aligned} λ0d0μndn=1;=h06(f[x0,x1]f0)=h06(f[x0,x1]P0);=1;=hn16(fnf[xn1,xn])=hn16(Pnf[xn1,xn]).
写成矩阵形式
[ 2 λ 0 μ 1 2 λ 1 ⋱ ⋱ ⋱ μ n − 1 2 λ n − 1 μ n 2 ] [ M 0 M 1 ⋮ M n − 1 M n ] = [ d 0 d 1 ⋮ d n − 1 d n ] (1.57) \begin{bmatrix} 2&\lambda_0\\ \mu_1&2&\lambda_1\\ &\ddots&\ddots&\ddots\\ &&\mu_{n-1}&2&\lambda_{n-1}\\ &&&\mu_n&2 \end{bmatrix}\begin{bmatrix}M_0\\M_1\\ \vdots\\M_{n-1}\\M_n \end{bmatrix}=\begin{bmatrix}d_0\\d_1\\ \vdots\\d_{n-1}\\d_n \end{bmatrix}\tag{1.57} 2μ1λ02λ1μn12μnλn12 M0M1Mn1Mn = d0d1dn1dn (1.57)
利用追赶法可解方程组.

#include <iostream> #include <cmath> #include <fstream> using namespace std; class scyt { float *x,*y,*d,*h,*u,*q,*a,*b,*c,*l,*r,*o,*M; int m; float y0,y3; public: scyt(); void qiudao(); void zgf(); void qiujie(); ~scyt(); }; void main() { scyt hello; hello.qiudao(); hello.zgf(); hello.qiujie(); } scyt::scyt() { ifstream fin("三次样条插值.txt"); for(float j;fin>>j;) { m=int(j); break; } x=new float[m]; y=new float[m]; d=new float[m]; h=new float[m-1]; u=new float[m-2]; q=new float[m-2]; a=new float[m-1]; b=new float[m]; c=new float[m-1]; l=new float[m]; r=new float[m-1];//此处的r为追赶法中的u; o=new float[m];//此处o为追赶法中的y M=new float[m];//此处M为追赶法中的x; int jishu=0; for(j;fin>>j;) { if(jishu<=m-1) x[jishu]=j; if(jishu>m-1&&jishu;<2*m) { y[jishu-m]=j; } if(jishu==2*m) { y0=j; } if(jishu==2*m+1) { y3=j; } jishu++; } fin.close(); } void scyt::qiudao() { for(int i=0;i<m-1;i++) { h[i]=x[i+1]-x[i]; } for(i=0;i<m-2;i++) { u[i]=h[i] / (h[i] + h[i+1]); } for(i=0;i<m-2;i++) { q[i]=1-u[i]; } d[0]=6/h[0]*((y[1]-y[0])/h[0]-y0); for(i=1;i<m-1;i++) { d[i]=6/(h[i-1]+h[i])*((y[i+1]-y[i])/h[i]-((y[i]-y[i-1])/h[i-1])); } d[m-1]=6/h[m-2]*(y3-(y[m-1]-y[m-2])/h[m-2]); } void scyt::zgf() { u[m-2]=1; for(int i=0;i<m;i++) { b[i]=2; } c[0]=1; for(i=1;i<m-1;i++) { c[i]=q[i-1]; } //........................................ l[0]=b[0]; for(i=0;i<m-1;i++) { r[i]=c[i] / l[i]; l[i+1]=b[i+1] - (u[i] * r[i]); } o[0]=d[0] / l[0]; for(i=1;i<m;i++) { o[i]=(d[i]-u[i-1]*o[i-1]) / l[i]; } M[m-1]=o[m-1]; for(i=m-2;i>=0;i--) { M[i]=o[i]-r[i] * M[i+1]; } cout<<m<<"个点的导数值分别是:"<<endl; for(i=0;i<m;i++) { cout<<"M"<<i+1<<"="; cout<<M[i]<<endl; } //M的值求出。。。。。。追赶法调用完毕 } void scyt::qiujie() { float S; for(;;) { float f; cout<<"请输入待求x的值(输入1000)时退出:"; cin>>f; if(f==1000) break; for(int i=0;i<m;i++) { if(f>x[i]&&f<x[i+1]) { S=pow((x[i+1]-f),3)*M[i]/(6*h[i]) + pow(f-x[i],3)*M[i+1]/(6*h[i]) + (x[i+1]-f)*(y[i]-h[i]*h[i]*M[i]/6)/h[i] + (f-x[i])*(y[i+1]-h[i]*h[i]*M[i+1]/6)/h[i]; cout<<"S["<<f<<"]="<<S<<endl; } } } } scyt::~scyt() { delete []x,y,d,h,u,q,a,b,c,l,r,o,M; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值