数模论坛

 找回密码
 注-册-帐-号
搜索
热搜: 活动 交友 discuz
12
返回列表 发新帖
楼主: dormouse_buaa

数值计算程序大放送-插值算法

[复制链接]
 楼主| 发表于 2005-1-19 23:04:29 | 显示全部楼层
//光滑不等距插值
//利用Akima方法
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//k- k>=0时计算第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//   k<0 计算插值点 t 的函数值和第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//t-存放指定插值点的值x, k>0时次参数无效,可以任取
//s-长度为5的数组,s[0]-s[3]返回三次多项式的系数,s[4]返回函数在t点的值
void enspl(double x[],double y[],int n,int k,double t,double 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;
}
 楼主| 发表于 2005-1-19 23:04:47 | 显示全部楼层
<>//光滑等距插值
//利用Akima方法
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//k- k&gt;=0时计算第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//   k&lt;0 计算插值点 t 的函数值和第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//t-存放指定插值点的值x, k&gt;0时次参数无效,可以任取
//s-长度为5的数组,s[0]-s[3]返回三次多项式的系数,s[4]返回函数在t点的值
void eespl(double x0,double h,int n,double y[],int k,double t,double 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&lt;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&lt;0)
  {
   s[4]=(y[1]*(t-x0)-y[0]*(t-x0-h))/h;
  }
        return;
}
    if (k&lt;0)
{
  if (t&lt;=x0+h)
  {
   kk=0;
  }
        else if (t&gt;=x0+(n-1)*h)
  {
   kk=n-2;
  }
        else
  {
   kk=1;
   m=n;
            while (((kk-m)!=1)&amp;&amp;((kk-m)!=-1))
   {
    l=(kk+m)/2;
                if (t&lt;x0+(l-1)*h)
    {
     m=l;
    }
                else
    {
     kk=l;
    }
   }
            kk=kk-1;
  }
}
    else
{
  kk=k;
}
    if (kk&gt;=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&lt;=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&gt;=(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)&amp;&amp;(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)&amp;&amp;(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&lt;0)
{
  p=t-(x0+kk*h);
        s[4]=s[0]+s[1]*p+s[2]*p*p+s[3]*p*p*p;
}
    return;
}</P>
 楼主| 发表于 2005-1-19 23:05:08 | 显示全部楼层
<>#include "stdlib.h"</P><>//第一种边界条件的三次样条函数插值、微商与积分
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//dy-长度为n的数组,调用时dy[0]存放给定左端点处的一阶导数值y0',
//   dy[n-1]存放给定的右端点处的一阶导数值y(n-1)',
//   返回时存放n个给定节点处的导数值
//dyy-长度为n的数组,返回时存放n个给定节点处的二阶导数值
//t-长度为m的数组,存放m个指定插值点的值ti
//m-指定插值点的个数
//z-长度为m的数组,返回时存放m个给定节点处值
//zd-长度为m的数组,返回时存放m个给定节点处一阶导数值
//dzz-长度为m的数组,返回时存放m个给定节点处二阶导数值
double espl1( double x[],
    double y[],
    int n,
    double dy[],
    double ddy[],
    double t[],
    int m,
    double z[],
    double dz[],
    double ddz[])
{
int i,j;
    double h0,h1,alpha,beta,g,*s;
    s=malloc(n*sizeof(double));
    s[0]=dy[0];
dy[0]=0.0;
    h0=x[1]-x[0];
    for (j=1;j&lt;=n-2;j++)
{
  h1=x[j+1]-x[j];
        alpha=h0/(h0+h1);
        beta=(1.0-alpha)*(y[j]-y[j-1])/h0;
        beta=3.0*(beta+alpha*(y[j+1]-y[j])/h1);
        dy[j]=-alpha/(2.0+(1.0-alpha)*dy[j-1]);
        s[j]=(beta-(1.0-alpha)*s[j-1]);
        s[j]=s[j]/(2.0+(1.0-alpha)*dy[j-1]);
        h0=h1;
}
    for (j=n-2;j&gt;=0;j--)
{
  dy[j]=dy[j]*dy[j+1]+s[j];
}
    for (j=0;j&lt;=n-2;j++)
{
  s[j]=x[j+1]-x[j];
}
    for (j=0;j&lt;=n-2;j++)
{
  h1=s[j]*s[j];
        ddy[j]=6.0*(y[j+1]-y[j])/h1-2.0*(2.0*dy[j]+dy[j+1])/s[j];
}
    h1=s[n-2]*s[n-2];
    ddy[n-1]=6.*(y[n-2]-y[n-1])/h1+2.*(2.*dy[n-1]+dy[n-2])/s[n-2];
    g=0.0;
    for (i=0;i&lt;=n-2;i++)
{
  h1=0.5*s*(y+y[i+1]);
        h1=h1-s*s*s*(ddy+ddy[i+1])/24.0;
        g=g+h1;
}
    for (j=0;j&lt;=m-1;j++)
{
  if (t[j]&gt;=x[n-1])
  {
   i=n-2;
  }
        else
  {
   i=0;
            while (t[j]&gt;x[i+1])
   {
    i=i+1;
   }
  }
        h1=(x[i+1]-t[j])/s;
        h0=h1*h1;
        z[j]=(3.0*h0-2.0*h0*h1)*y;
        z[j]=z[j]+s*(h0-h0*h1)*dy;
        dz[j]=6.0*(h0-h1)*y/s;
        dz[j]=dz[j]+(3.0*h0-2.0*h1)*dy;
        ddz[j]=(6.0-12.0*h1)*y/(s*s);
        ddz[j]=ddz[j]+(2.0-6.0*h1)*dy/s;
        h1=(t[j]-x)/s;
        h0=h1*h1;
        z[j]=z[j]+(3.0*h0-2.0*h0*h1)*y[i+1];
        z[j]=z[j]-s*(h0-h0*h1)*dy[i+1];
        dz[j]=dz[j]-6.0*(h0-h1)*y[i+1]/s;
        dz[j]=dz[j]+(3.0*h0-2.0*h1)*dy[i+1];
        ddz[j]=ddz[j]+(6.0-12.0*h1)*y[i+1]/(s*s);
        ddz[j]=ddz[j]-(2.0-6.0*h1)*dy[i+1]/s;
}
    free(s);
    return(g);
}</P>
 楼主| 发表于 2005-1-19 23:05:32 | 显示全部楼层
//第二种边界条件的三次样条函数插值、微商与积分
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//dy-长度为n的数组,返回时存放n个给定节点处的导数值
//dyy-长度为n的数组,调用时dyy[0]存放给定左端点处的二阶导数值y0'',
//   dyy[n-1]存放给定的右端点处的二阶导数值y(n-1)'',
//   返回时存放n个给定节点处的二阶导数值
//t-长度为m的数组,存放m个指定插值点的值ti
//m-指定插值点的个数
//z-长度为m的数组,返回时存放m个给定节点处值
//zd-长度为m的数组,返回时存放m个给定节点处一阶导数值
//dzz-长度为m的数组,返回时存放m个给定节点处二阶导数值
double espl2(
    int n,
    int m,
    double x[],
    double y[],
    double dy[],
    double ddy[],
    double t[],
    double z[],
    double dz[],
    double ddz[])
{
int i,j;
    double h0,h1,alpha,beta,g,*s;
    s=malloc(n*sizeof(double));
    dy[0]=-0.5;
    h0=x[1]-x[0];
    s[0]=3.0*(y[1]-y[0])/(2.0*h0)-ddy[0]*h0/4.0;
    for (j=1;j&lt;=n-2;j++)
{
  h1=x[j+1]-x[j];
        alpha=h0/(h0+h1);
        beta=(1.0-alpha)*(y[j]-y[j-1])/h0;
        beta=3.0*(beta+alpha*(y[j+1]-y[j])/h1);
        dy[j]=-alpha/(2.0+(1.0-alpha)*dy[j-1]);
        s[j]=(beta-(1.0-alpha)*s[j-1]);
        s[j]=s[j]/(2.0+(1.0-alpha)*dy[j-1]);
        h0=h1;
}
    dy[n-1]=(3.0*(y[n-1]-y[n-2])/h1+ddy[n-1]*h1/2.0-s[n-2])/(2.0+dy[n-2]);
    for (j=n-2;j&gt;=0;j--)
{
  dy[j]=dy[j]*dy[j+1]+s[j];
}
    for (j=0;j&lt;=n-2;j++)
{
  s[j]=x[j+1]-x[j];
}
    for (j=0;j&lt;=n-2;j++)
{
  h1=s[j]*s[j];
        ddy[j]=6.0*(y[j+1]-y[j])/h1-2.0*(2.0*dy[j]+dy[j+1])/s[j];
}
    h1=s[n-2]*s[n-2];
    ddy[n-1]=6.*(y[n-2]-y[n-1])/h1+2.*(2.*dy[n-1]+dy[n-2])/s[n-2];
    g=0.0;
    for (i=0;i&lt;=n-2;i++)
{
  h1=0.5*s*(y+y[i+1]);
        h1=h1-s*s*s*(ddy+ddy[i+1])/24.0;
        g=g+h1;
}
    for (j=0;j&lt;=m-1;j++)
{
  if (t[j]&gt;=x[n-1])
  {
   i=n-2;
  }
        else
  {
   i=0;
            while (t[j]&gt;x[i+1])
   {
    i=i+1;
   }
  }
        h1=(x[i+1]-t[j])/s;
        h0=h1*h1;
        z[j]=(3.0*h0-2.0*h0*h1)*y;
        z[j]=z[j]+s*(h0-h0*h1)*dy;
        dz[j]=6.0*(h0-h1)*y/s;
        dz[j]=dz[j]+(3.0*h0-2.0*h1)*dy;
        ddz[j]=(6.0-12.0*h1)*y/(s*s);
        ddz[j]=ddz[j]+(2.0-6.0*h1)*dy/s;
        h1=(t[j]-x)/s;
        h0=h1*h1;
        z[j]=z[j]+(3.0*h0-2.0*h0*h1)*y[i+1];
        z[j]=z[j]-s*(h0-h0*h1)*dy[i+1];
        dz[j]=dz[j]-6.0*(h0-h1)*y[i+1]/s;
        dz[j]=dz[j]+(3.0*h0-2.0*h1)*dy[i+1];
        ddz[j]=ddz[j]+(6.0-12.0*h1)*y[i+1]/(s*s);
        ddz[j]=ddz[j]-(2.0-6.0*h1)*dy[i+1]/s;
}
    free(s);
    return(g);
}
 楼主| 发表于 2005-1-19 23:05:48 | 显示全部楼层
//第三种边界条件的三次样条函数插值、微商与积分
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//dy-长度为n的数组,返回时存放n个给定节点处的导数值
//dyy-长度为n的数组,返回时存放n个给定节点处的二阶导数值
//t-长度为m的数组,存放m个指定插值点的值ti
//m-指定插值点的个数
//z-长度为m的数组,返回时存放m个给定节点处值
//zd-长度为m的数组,返回时存放m个给定节点处一阶导数值
//dzz-长度为m的数组,返回时存放m个给定节点处二阶导数值
double espl3( int n,
    int m,
    double x[],
    double y[],
    double dy[],
    double ddy[],
    double t[],
    double z[],
    double dz[],
    double ddz[])
{
int i,j;
    double h0,y0,h1,y1,alpha,beta,u,g,*s;
    s=malloc(n*sizeof(double));
    h0=x[n-1]-x[n-2];
    y0=y[n-1]-y[n-2];
    dy[0]=0.0;
ddy[0]=0.0;
ddy[n-1]=0.0;
    s[0]=1.0;
s[n-1]=1.0;
    for (j=1;j&lt;=n-1;j++)
{
  h1=h0;
  y1=y0;
  h0=x[j]-x[j-1];
  y0=y[j]-y[j-1];
  alpha=h1/(h1+h0);
  beta=3.0*((1.0-alpha)*y1/h1+alpha*y0/h0);
  if (j&lt;n-1)
  {
   u=2.0+(1.0-alpha)*dy[j-1];
   dy[j]=-alpha/u;
   s[j]=(alpha-1.0)*s[j-1]/u;
   ddy[j]=(beta-(1.0-alpha)*ddy[j-1])/u;
  }
}
    for (j=n-2;j&gt;=1;j--)
{
  s[j]=dy[j]*s[j+1]+s[j];
        ddy[j]=dy[j]*ddy[j+1]+ddy[j];
}
    dy[n-2]=(beta-alpha*ddy[1]-(1.0-alpha)*ddy[n-2])/(alpha*s[1]+(1.0-alpha)*s[n-2]+2.0);
    for (j=2;j&lt;=n-1;j++)
{
        dy[j-2]=s[j-1]*dy[n-2]+ddy[j-1];
}
    dy[n-1]=dy[0];
    for (j=0;j&lt;=n-2;j++)
{
  s[j]=x[j+1]-x[j];
}
    for (j=0;j&lt;=n-2;j++)
{
  h1=s[j]*s[j];
        ddy[j]=6.0*(y[j+1]-y[j])/h1-2.0*(2.0*dy[j]+dy[j+1])/s[j];
}
    h1=s[n-2]*s[n-2];
    ddy[n-1]=6.*(y[n-2]-y[n-1])/h1+2.*(2.*dy[n-1]+dy[n-2])/s[n-2];
    g=0.0;
    for (i=0;i&lt;=n-2;i++)
{
  h1=0.5*s*(y+y[i+1]);
        h1=h1-s*s*s*(ddy+ddy[i+1])/24.0;
        g=g+h1;
}
    for (j=0;j&lt;=m-1;j++)
{
  h0=t[j];
        while (h0&gt;=x[n-1])
  {
   h0=h0-(x[n-1]-x[0]);
  }
        while (h0&lt;x[0])
  {
   h0=h0+(x[n-1]-x[0]);
  }
        i=0;
        while (h0&gt;x[i+1])
  {
   i=i+1;
  }
        u=h0;
        h1=(x[i+1]-u)/s;
        h0=h1*h1;
        z[j]=(3.0*h0-2.0*h0*h1)*y;
        z[j]=z[j]+s*(h0-h0*h1)*dy;
        dz[j]=6.0*(h0-h1)*y/s;
        dz[j]=dz[j]+(3.0*h0-2.0*h1)*dy;
        ddz[j]=(6.0-12.0*h1)*y/(s*s);
        ddz[j]=ddz[j]+(2.0-6.0*h1)*dy/s;
        h1=(u-x)/s;
        h0=h1*h1;
        z[j]=z[j]+(3.0*h0-2.0*h0*h1)*y[i+1];
        z[j]=z[j]-s*(h0-h0*h1)*dy[i+1];
        dz[j]=dz[j]-6.0*(h0-h1)*y[i+1]/s;
        dz[j]=dz[j]+(3.0*h0-2.0*h1)*dy[i+1];
        ddz[j]=ddz[j]+(6.0-12.0*h1)*y[i+1]/(s*s);
        ddz[j]=ddz[j]-(2.0-6.0*h1)*dy[i+1]/s;
}
    free(s);
    return(g);
}
 楼主| 发表于 2005-1-19 23:06:06 | 显示全部楼层
#include "math.h"
//二元三点插值
//x-长度为n的数组,存放给定的n*m个节点X方向的n个坐标xi,要求增序
//y-长度为m的数组,存放给定的n*m个节点Y方向的m个坐标yi,要求增序
//z-长度为n*m的数组,存放n*m个节点的函数值
//n-给定X方向节点的个数
//m-给定Y方向节点的个数
//u-存放指定插值点的值x
//v-存放指定插值点的值y
double eslq3( int m,
    int n,
    double u,
    double v,
    double x[],
    double y[],
    double z[])
{
int nn,mm,ip,iq,i,j,k,l;
    double b[3],h,w;
    nn=3;
    if (n&lt;=3)
{
  ip=0;
  nn=n;
}
    else if (u&lt;=x[1])
{
  ip=0;
}
    else if (u&gt;=x[n-2])
{
  ip=n-3;
}
    else
{
  i=1;
  j=n;
        while (((i-j)!=1)&amp;&amp;((i-j)!=-1))
  {
   l=(i+j)/2;
            if (u&lt;x[l-1])
   {
    j=l;
   }
            else i=l;
  }
        if (fabs(u-x[i-1])&lt;fabs(u-x[j-1]))
  {
   ip=i-2;
  }
        else
  {
   ip=i-1;
  }
}
    mm=3;
    if (m&lt;=3)
{
  iq=0;
  mm=m;
}
    else if (v&lt;=y[1])
{
  iq=0;
}
    else if (v&gt;=y[m-2])
{
  iq=m-3;
}
    else
{
  i=1;
  j=m;
        while (((i-j)!=1)&amp;&amp;((i-j)!=-1))
  {
   l=(i+j)/2;
            if (v&lt;y[l-1])
   {
    j=l;
   }
            else
   {
    i=l;
   }
  }
        if (fabs(v-y[i-1])&lt;fabs(v-y[j-1]))
  {
   iq=i-2;
  }
        else
  {
   iq=i-1;
  }
}
    for (i=0;i&lt;=nn-1;i++)
{
  b=0.0;
        for (j=0;j&lt;=mm-1;j++)
  {
   k=m*(ip+i)+(iq+j);
            h=z[k];
            for (k=0;k&lt;=mm-1;k++)
   {
    if (k!=j)
    {
     h=h*(v-y[iq+k])/(y[iq+j]-y[iq+k]);
    }
    b=b+h;
   }
  }
}
    w=0.0;
    for (i=0;i&lt;=nn-1;i++)
{
  h=b;
        for (j=0;j&lt;=nn-1;j++)
  {
   if (j!=i)
   {
    h=h*(u-x[ip+j])/(x[ip+i]-x[ip+j]);
   }
   w=w+h;
  }
}
    return(w);
}
 楼主| 发表于 2005-1-19 23:06:26 | 显示全部楼层

//二元全区间插值
//以插值点为中心在X,Y方向前后各取4个坐标进行插值
//x-长度为n的数组,存放给定的n*m个节点X方向的n个坐标xi,要求增序
//y-长度为m的数组,存放给定的n*m个节点Y方向的m个坐标yi,要求增序
//z-长度为n*m的数组,存放n*m个节点的函数值
//n-给定X方向节点的个数
//m-给定Y方向节点的个数
//u-存放指定插值点的值x
//v-存放指定插值点的值y
double eslgq( int n,
    int m,
    double x[],
    double y[],
    double z[],
    double u,
    double v)
{
int ip,ipp,i,j,l,iq,iqq,k;
    double h,w,b[10];
    if (u&lt;=x[0])
{
  ip=1;
  ipp=4;
}
    else if (u&gt;=x[n-1])
{
  ip=n-3;
  ipp=n;
}
    else
{
  i=1;
  j=n;
        while (((i-j)!=1)&amp;&amp;((i-j)!=-1))
  {
   l=(i+j)/2;
            if (u&lt;x[l-1])
   {
    j=l;
   }
            else
   {
    i=l;
   }
  }
        ip=i-3;
  ipp=i+4;
}
    if (ip&lt;1)
{
  ip=1;
}
    if (ipp&gt;n)
{
  ipp=n;
}
    if (v&lt;=y[0])
{
  iq=1;
  iqq=4;
}
    else if (v&gt;=y[m-1])
{
  iq=m-3;
  iqq=m;
}
    else
{
  i=1;
  j=m;
        while (((i-j)!=1)&amp;&amp;((i-j)!=-1))
  {
   l=(i+j)/2;
            if (v&lt;y[l-1])
   {
    j=l;
   }
            else i=l;
  }
        iq=i-3;
  iqq=i+4;
}
    if (iq&lt;1)
{
  iq=1;
}
    if (iqq&gt;m)
{
  iqq=m;
}
    for (i=ip-1;i&lt;=ipp-1;i++)
{
  b[i-ip+1]=0.0;
        for (j=iq-1;j&lt;=iqq-1;j++)
  {
   h=z[m*i+j];
            for (k=iq-1;k&lt;=iqq-1;k++)
    if (k!=j)
    {
     h=h*(v-y[k])/(y[j]-y[k]);
    }
    b[i-ip+1]=b[i-ip+1]+h;
  }
}
    w=0.0;
    for (i=ip-1;i&lt;=ipp-1;i++)
{
  h=b[i-ip+1];
        for (j=ip-1;j&lt;=ipp-1;j++)
   if (j!=i)
   {
    h=h*(u-x[j])/(x-x[j]);
   }
   w=w+h;
}
    return(w);
}
 楼主| 发表于 2005-1-19 23:06:41 | 显示全部楼层
//////////////////////////////////////////////////////////////
//一元全区间不等距插值,
//利用七次(两边为四次)拉格朗日插值多项式计算插值点t的函数值
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值x
double enlgr(double x[],double y[],int n,double t);
//////////////////////////////////////////////////////////////
//一元全区间等距插值
//利用七次(两边为四次)拉格朗日插值多项式计算插值点t的函数值
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值 x
double eelgr(double x0,double h,int n,double y[],double t);
//////////////////////////////////////////////////////////////
//一元三点不等距插值
//利用抛物线插值公式计算指定插值点t的函数值
//x-长度为n的数组,存放n个不等距节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值x
double enlg3(double x[],double y[],int n,double t);
//////////////////////////////////////////////////////////////
//一元三点等距插值
//利用抛物线插值公式计算指定插值点t的函数值
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值 x
double eelg3(double x0,double h,int n,double y[],double t);
//////////////////////////////////////////////////////////////
//连分式不等距插值
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值x
double enpqs(double x[],double y[],int n,double t);
//////////////////////////////////////////////////////////////
//连分式等距插值
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值 x
double eepqs(double x0,double h,int n,double y[],double t);
//////////////////////////////////////////////////////////////
//埃尔米特(Hermite)不等距插值
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//dy-长度为n的数组,存放n个节点上的一阶导数值
//n-给定节点的个数
//t-存放指定插值点的值x
double enhmt(double x[],double y[],double dy[],int n,double t);
//////////////////////////////////////////////////////////////
//埃尔米特(Hermite)等距插值
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//dy-长度为n的数组,存放n个节点上的一阶导数值
//n-给定节点的个数
//t-存放指定插值点的值 x
double eehmt(double x0,double h,int n,double y[],double dy[],double t);
//////////////////////////////////////////////////////////////
//埃特金(Aitken)不等距逐步插值
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值x
//eps-指定的精度要求
double enatk(double x[],double y[],int n,double t,double eps);
//////////////////////////////////////////////////////////////
//埃特金(Aitken)等距逐步插值
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//t-存放指定插值点的值x
//eps-指定的精度要求
double eeatk(double x0,double h,int n,double y[],double t,double eps);
//////////////////////////////////////////////////////////////
//光滑不等距插值
//利用Akima方法
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//k- k&gt;=0时计算第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//   k&lt;0 计算插值点 t 的函数值和第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//t-存放指定插值点的值x, k&gt;0时次参数无效,可以任取
//s-长度为5的数组,s[0]-s[3]返回三次多项式的系数,s[4]返回函数在t点的值
void enspl(double x[],double y[],int n,int k,double t,double s[5]);
//////////////////////////////////////////////////////////////
//光滑等距插值
//利用Akima方法
//x0-第一个节点x0
//h-等距节点的步长
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//k- k&gt;=0时计算第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//   k&lt;0 计算插值点 t 的函数值和第 k 个子区间的三次多项式的系数s0,s1,s2,s3
//t-存放指定插值点的值x, k&gt;0时次参数无效,可以任取
//s-长度为5的数组,s[0]-s[3]返回三次多项式的系数,s[4]返回函数在t点的值
void eespl(double x0,double h,int n,double y[],int k,double t,double s[5]);
//////////////////////////////////////////////////////////////
 楼主| 发表于 2005-1-19 23:07:08 | 显示全部楼层
//////////////////////////////////////////////////////////////
//第一种边界条件的三次样条函数插值、微商与积分
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//dy-长度为n的数组,调用时dy[0]存放给定左端点处的一阶导数值y0',
//   dy[n-1]存放给定的右端点处的一阶导数值y(n-1)',
//   返回时存放n个给定节点处的导数值
//dyy-长度为n的数组,返回时存放n个给定节点处的二阶导数值
//t-长度为m的数组,存放m个指定插值点的值ti
//m-指定插值点的个数
//z-长度为m的数组,返回时存放m个给定节点处值
//zd-长度为m的数组,返回时存放m个给定节点处一阶导数值
//dzz-长度为m的数组,返回时存放m个给定节点处二阶导数值
double espl1( double x[],double y[],int n,double dy[],
    double ddy[],double t[],int m,double z[],double dz[],double ddz[]);
//////////////////////////////////////////////////////////////
//第二种边界条件的三次样条函数插值、微商与积分
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//dy-长度为n的数组,返回时存放n个给定节点处的导数值
//dyy-长度为n的数组,调用时dyy[0]存放给定左端点处的二阶导数值y0'',
//   dyy[n-1]存放给定的右端点处的二阶导数值y(n-1)'',
//   返回时存放n个给定节点处的二阶导数值
//t-长度为m的数组,存放m个指定插值点的值ti
//m-指定插值点的个数
//z-长度为m的数组,返回时存放m个给定节点处值
//zd-长度为m的数组,返回时存放m个给定节点处一阶导数值
//dzz-长度为m的数组,返回时存放m个给定节点处二阶导数值
double espl2(int n,int m,double x[],double y[],double dy[],double ddy[],
    double t[],double z[],double dz[],double ddz[]);
//////////////////////////////////////////////////////////////
//第三种边界条件的三次样条函数插值、微商与积分
//x-长度为n的数组,存放n个节点xi,要求增序
//y-长度为n的数组,存放n个节点yi
//n-给定节点的个数
//dy-长度为n的数组,返回时存放n个给定节点处的导数值
//dyy-长度为n的数组,返回时存放n个给定节点处的二阶导数值
//t-长度为m的数组,存放m个指定插值点的值ti
//m-指定插值点的个数
//z-长度为m的数组,返回时存放m个给定节点处值
//zd-长度为m的数组,返回时存放m个给定节点处一阶导数值
//dzz-长度为m的数组,返回时存放m个给定节点处二阶导数值
double espl3( int n, int m, double x[], double y[], double dy[],
    double ddy[], double t[], double z[], double dz[], double ddz[]);
//////////////////////////////////////////////////////////////
 楼主| 发表于 2005-1-19 23:07:22 | 显示全部楼层
//////////////////////////////////////////////////////////////
//二元三点插值
//x-长度为n的数组,存放给定的n*m个节点X方向的n个坐标xi,要求增序
//y-长度为m的数组,存放给定的n*m个节点Y方向的m个坐标yi,要求增序
//z-长度为n*m的数组,存放n*m个节点的函数值
//n-给定X方向节点的个数
//m-给定Y方向节点的个数
//u-存放指定插值点的值x
//v-存放指定插值点的值y
double eslq3( int m,int n,double u,double v,double x[],double y[],double z[]);
//////////////////////////////////////////////////////////////
//二元全区间插值
//以插值点为中心在X,Y方向前后各取4个坐标进行插值
//x-长度为n的数组,存放给定的n*m个节点X方向的n个坐标xi,要求增序
//y-长度为m的数组,存放给定的n*m个节点Y方向的m个坐标yi,要求增序
//z-长度为n*m的数组,存放n*m个节点的函数值
//n-给定X方向节点的个数
//m-给定Y方向节点的个数
//u-存放指定插值点的值x
//v-存放指定插值点的值y
double eslgq( int n, int m, double x[], double y[], double z[], double u, double v);
//////////////////////////////////////////////////////////////
您需要登录后才可以回帖 登录 | 注-册-帐-号

本版积分规则

小黑屋|手机版|Archiver|数学建模网 ( 湘ICP备11011602号 )

GMT+8, 2024-11-27 22:28 , Processed in 0.059852 second(s), 12 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表