继续
/* 埃特金不等距逐步插值
* 给定n个不等距结点xi上的函数值f(xi)及精度要求,用埃特金(Aitken)插值公式计算指定插值点t处的函数近似值f(t)
* x ----双精度实型一维数组,长n。存放给定n个不等距结点的值
* y ----双精度实型一维数组,长n。存放给定n个不等距结点上的函数值
* n ----整形变量。给定不等距结点的个数
* t ----双精度实型变量。指定插值点的值
* eps---双精度实型变量。插值的精度要求
*/
#include <math.h>
double aiatkn(x,y,n,t,eps)
int n;
double t,eps,x[],y[];
{
int i,j,k,m,l;
double z,xx[10],yy[10];
z=0.0;
if(n<1) return(z);
if(n==1) {z=y[0];return(z);}
m=10;
if(m>n) m=n;
if(t<=x[0]) k=1;
else if(t>=x[n-1]) k=n;
else
{
k=1;j=n;
while((k-j!=1) && (k-j!=-1))
{
l=(k+j)/2;
if(t<x[l-1]) j=l;
else k=l;
}
if(fabs(t-x[l-1])>fabs(t-x[j-1])) k=j;
}
j=1;l=0;
for(i=1;i<=m;i++)
{
k=k+j*l;
if((k<1)||(k>n)) {l=l+1;j=-j;k=k+j*l;}
xx[i-1]=x[k-1];
yy[i-1]=y[k-1];
l=l+1;j=-j;
}
i=0;
do
{
i=i+1;z=yy;
for(j=0;j<=i-1;j++)
z=yy[j]+(t-xx[j])*(yy[j]-z)/(xx[j]-xx);
yy=z;
}
while((i!=m-1) && (fabs(yy-yy[i-1])>eps));
return(z);
}
/* 埃特金等距逐步插值
* x0----双精度实型变量。n个等距结点中的第一个结点值
* h ----双精度实型变量。n个等距结点的步长
* n ----int,等距结点的个数
* y ----双精度实型一维数组,长n。存放n个等距结点上的函数值
* t ----双精度实型变量。指定插值点的值
* eps---双精度实型变量。插值的精度要求
*/
#include <math.h>
double ajatkn(x0,h,n,y,t,eps)
int n;
double x0,h,t,eps,y[];
{
int i,j,k,m,l;
double z,xx[10],yy[10];
z=0.0;
if(n<1) return(z);
if(n==1) {z=y[0];return(z);}
m=10;
if(m>n) m=n;
if(t<x0) k=1;
else if(t>=x0+(n-1)*h) k=n;
else
{
k=1;j=n;
while((k-j!=1) && (k-j!=-1))
{
l=(k+j)/2;
if(t<x0+(l-1)*h) j=l;
else k=l;
}
if(fabs(t-(x0+(l-1)*h)) > fabs(t-(x0+(j-1)*h))) k=j;
}
j=1;l=0;
for(i=1;i<=m;i++)
{
k=k+j*l;
if((k<1) || (k>n))
{l=l+1;j=-j;k=k+j*l;}
xx[i-1]=x0+(k-1)*h;yy[i-1]=y[k-1];
l=l+1;j=-j;
}
i=0;
do
{
i=i+1;z=yy;
for(j=0;j<=i-1;j++)
z=yy[j]+(t-xx[j])*(yy[j]-z)/(xx[j]-xx);
yy=z;
}
while((i!=m-1) && (fabs(yy-yy[i-1])>eps));
return(z);
}
/* 光滑不等距插值
* 给定n个不等钜结点xi上的函数值yi=f(xi),利用阿克玛(Akima)方法,计算指定子区间上的三次插值多项式与指定插值点上的函数值
* x ----双精度实型一维数组,长n。存放给定的n个不等距结点值
* y ----双精度实型一维数组,长n。存放给定的n个不等距结点上的函数值
* n ----int,给定不等距节点的个数
* k ----int,若k>=0,表示只计算第k个子区间[xk,xk+1]上的三次多项式的系数s0,s1,s2,s3.若k<0,表示需要计算指定插值点t处的函数近似值f(t)和系数
* t ----双精度实型变量。制定插值点值。当k>=0时,此形参对本函数不起作用,可任意
* s ----双精度实型一维数组,长5。s0到s3返回三次多项式的系数,s4返回制定插值点t处的函数近似值(k<0时)或任意(k>=0时)
*/
#include <math.h>
void akspl(x,y,n,k,t,s)
int n,k;
double t,x[],y[],s[5];
{
int kk,m,l;
double u[5],p,q;
s[4]=0.0;s[0]=0.0;s[1]=0.0;s[2]=0.0;s[3]=0.0;
if(n<1) return;
if(n==1) {s[0]=y[0];s[4]=y[0];return;}
if(n==2)
{
s[0]=y[0];s[1]=(y[1]-y[0])/(x[1]-x[0]);
if(k<0)
s[4]=(y[0]*(t-x[1])-y[1]*(t-x[0]))/(x[0]-x[1]);
return;
}
if(k<0)
{
if(t<=x[1]) kk=0;
else if(t>=x[n-1]) kk=n-2;
else
{
kk=1;m=n;
while(((kk-m)!=1) && ((kk-m)!=-1))
{
l=(kk+m)/2;
if(t<x[l-1]) m=l;
else kk=l;
}
kk=kk-1;
}
}
else kk=k;
if(kk>=n-1) kk=n-2;
u[2]=(y[kk+1]-y[kk])/(x[kk+1]-x[kk]);
if(n==3)
{
if(kk==0)
{
u[3]=(y[2]-y[1])/(x[2]-x[1]);
u[4]=2.0*u[3]-u[2];
u[1]=2.0*u[2]-u[3];
u[0]=2.0*u[1]-u[2];
}
else
{
u[1]=(y[1]-y[0])/(x[1]-x[0]);
u[0]=2.0*u[1]-u[2];
u[3]=2.0*u[2]-u[1];
u[4]=2.0*u[3]-u[2];
}
}
else
{
if(kk<=1)
{
u[3]=(y[kk+2]-y[kk+1])/(x[kk+2]-x[kk+1]);
if(kk==1)
{
u[1]=(y[1]-y[0])/(x[1]-x[0]);
u[0]=2.0*u[1]-u[2];
if(n==4) u[4]=2.0*u[3]-u[2];
else u[4]=(y[4]-y[3])/(x[4]-x[3]);
}
else
{
u[1]=2.0*u[2]-u[3];
u[0]=2.0*u[1]-u[2];
u[4]=(y[3]-y[2])/(x[3]-x[2]);
}
}
else if(kk>=(n-3))
{
u[1]=(y[kk]-y[kk-1])/(x[kk]-x[kk-1]);
if(kk==(n-3))
{
u[3]=(y[n-1]-y[n-2])/(x[n-1]-x[n-2]);
u[4]=2.0*u[3]-u[2];
if(n==4) u[0]=2.0*u[1]-u[2];
else u[0]=(y[kk-1]-y[kk-2])/(x[kk-1]-x[kk-2]);
}
else
{
u[3]=2.0*u[2]-u[1];
u[4]=2.0*u[3]-u[2];
u[0]=(y[kk-1]-y[kk-2])/(x[kk-1]-x[kk-2]);
}
}
else
{
u[1]=(y[kk]-y[kk-1])/(x[kk]-x[kk-1]);
u[0]=(y[kk-1]-y[kk-2])/(x[kk-1]-x[kk-2]);
u[3]=(y[kk+2]-y[kk+1])/(x[kk+2]-x[kk+1]);
u[4]=(y[kk+3]-y[kk+2])/(x[kk+3]-x[kk+2]);
}
}
s[0]=fabs(u[3]-u[2]);
s[1]=fabs(u[0]-u[1]);
if((s[0]+1.0==1.0) && (s[1]+1.0==1.0))
p=(u[1]+u[2])/2.0;
else p=(s[0]*u[1]+s[1]*u[2])/(s[0]+s[1]);
s[0]=fabs(u[3]-u[4]);
s[1]=fabs(u[2]-u[1]);
if((s[0]+1.0==1.0) && (s[1]+1.0==1.0))
q=(u[2]+u[3])/2.0;
else q=(s[0]*u[2]+s[1]*u[3])/(s[0]+s[1]);
s[0]=y[kk];
s[1]=p;
s[3]=x[kk+1]-x[kk];
s[2]=(3.0*u[2]-2.0*p-q)/s[3];
s[3]=(q+p-2.0*u[2])/(s[3]*s[3]);
if(k<0)
{
p=t-x[kk];
s[4]=s[0]+s[1]*p+s[2]*p*p+s[3]*p*p*p;
}
return;
}
/* 光滑不等距插值
* 给定n个不等钜结点xi上的函数值yi=f(xi),利用阿克玛(Akima)方法,计算指定子区间上的三次插值多项式与指定插值点上的函数值
* x0----双精度实型变量。n个等距结点中的第一个结点值
* h ----双精度实型变量。n个等距结点的步长
* n ----int,等距结点的个数
* y ----双精度实型一维数组,长n。存放n个等距结点上的函数值
* k ----int,若k>=0,表示只计算第k个子区间[xk,xk+1]上的三次多项式的系数s0,s1,s2,s3.若k<0,表示需要计算指定插值点t处的函数近似值f(t)和系数
* t ----双精度实型变量。指定插值点的值
* s ----双精度实型一维数组,长5。s0到s3返回三次多项式的系数,s4返回制定插值点t处的函数近似值(k<0时)或任意(k>=0时)
*/
#include <math.h>
void alspl(x0,h,n,y,k,t,s)
int n,k;
double t,x0,h,y[],s[5];
{
int kk,m,l;
double u[5],p,q;
s[4]=0.0;s[0]=0.0;s[1]=0.0;s[2]=0.0;s[3]=0.0;
if(n<1) return;
if(n==1) {s[0]=y[0];s[4]=y[0];return;}
if(n==2)
{
s[0]=y[0];s[1]=(y[1]-y[0])/h;
if(k<0)
s[4]=(y[1]*(t-x0)-y[0]*(t-x0-h))/h;
return;
}
if(k<0)
{
if(t<=x0+h) kk=0;
else if(t>=x0+(n-1)*h) kk=n-2;
else
{
kk=1;m=n;
while(((kk-m)!=1) && ((kk-m)!=-1))
{
l=(kk+m)/2;
if(t<x0+(l-1)*h) m=l;
else kk=l;
}
kk=kk-1;
}
}
else kk=k;
if(kk>=n-1) kk=n-2;
u[2]=(y[kk+1]-y[kk])/h;
if(n==3)
{
if(kk==0)
{
u[3]=(y[2]-y[1])/h;
u[4]=2.0*u[3]-u[2];
u[1]=2.0*u[2]-u[3];
u[0]=2.0*u[1]-u[2];
}
else
{
u[1]=(y[1]-y[0])/h;
u[0]=2.0*u[1]-u[2];
u[3]=2.0*u[2]-u[1];
u[4]=2.0*u[3]-u[2];
}
}
else
{
if(kk<=1)
{
u[3]=(y[kk+2]-y[kk+1])/h;
if(kk==1)
{
u[1]=(y[1]-y[0])/h;
u[0]=2.0*u[1]-u[2];
if(n==4) u[4]=2.0*u[3]-u[2];
else u[4]=(y[4]-y[3])/h;
}
else
{
u[1]=2.0*u[2]-u[3];
u[0]=2.0*u[1]-u[2];
u[4]=(y[3]-y[2])/h;
}
}
else if(kk>=(n-3))
{
u[1]=(y[kk]-y[kk-1])/h;
if(kk==(n-3))
{
u[3]=(y[n-1]-y[n-2])/h;
u[4]=2.0*u[3]-u[2];
if(n==4) u[0]=2.0*u[1]-u[2];
else u[0]=(y[kk-1]-y[kk-2])/h;
}
else
{
u[3]=2.0*u[2]-u[1];
u[4]=2.0*u[3]-u[2];
u[0]=(y[kk-1]-y[kk-2])/h;
}
}
else
{
u[1]=(y[kk]-y[kk-1])/h;
u[0]=(y[kk-1]-y[kk-2])/h;
u[3]=(y[kk+2]-y[kk+1])/h;
u[4]=(y[kk+3]-y[kk+2])/h;
}
}
s[0]=fabs(u[3]-u[2]);
s[1]=fabs(u[0]-u[1]);
if((s[0]+1.0==1.0) && (s[1]+1.0==1.0))
p=(u[1]+u[2])/2.0;
else p=(s[0]*u[1]+s[1]*u[2])/(s[0]+s[1]);
s[0]=fabs(u[3]-u[4]);
s[1]=fabs(u[2]-u[1]);
if((s[0]+1.0==1.0) && (s[1]+1.0==1.0))
q=(u[2]+u[3])/2.0;
else q=(s[0]*u[2]+s[1]*u[3])/(s[0]+s[1]);
s[0]=y[kk];
s[1]=p;
s[3]=h;
s[2]=(3.0*u[2]-2.0*p-q)/s[3];
s[3]=(q+p-2.0*u[2])/(s[3]*s[3]);
if(k<0)
{
p=t-(x0+kk*h);
s[4]=s[0]+s[1]*p+s[2]*p*p+s[3]*p*p*p;
}
return;
} |