数值分析论文几种插值方法的比较.docx
《数值分析论文几种插值方法的比较.docx》由会员分享,可在线阅读,更多相关《数值分析论文几种插值方法的比较.docx(15页珍藏版)》请在冰点文库上搜索。
数值分析论文几种插值方法的比较
数值分析论文
——几种插值方法的比较
1.插值法概述
插值法是函数逼近的重要方法之一,有着广泛的应用!
在生产和实验中,函数
或者其表达式不便于计算复杂或者无表达式而只有函数在给定点的函数值(或其导数值),此时我们希望建立一个简单的而便于计算的函数
,使其近似的代替
,有很多种插值法,其中以拉格朗日(Lagrange)插值和牛顿(Newton)插值为代表的多项式插值最有特点,常用的插值还有Hermite插值,分段插值和样条插值.这里主要介绍拉格朗日(Lagrange)插值和牛顿(Newton)插值和埃尔米特插值(Hermite插值)。
2.插值方法的比较
2.1拉格朗日插值
2.1.1基本原理
构造
次多项式
,这是
不超过
次的多项式,其中基函数:
显然
满足
=
此时
误差
其中
∈
且依赖于
,
.
很显然,当
,插值节点只有两个
时
其中基函数
=
,
=
2.1.2优缺点
可对插值函数选择多种不同的函数类型,由于代数多项式具有简单和一些良好的特性,故常选用代数多项式作为插值函数。
利用插值基函数很容易得到拉格朗日插值多项式,公式结构紧凑,在理论分析中甚为方便,但当插值节点增减时全部插值基函数
均要随之变化,整个公式也将发生变化,这在实际计算中是很不方便的,为了克服这一缺点,提出了牛顿插值可以克服这一缺点。
2.1.3数值实验
程序如下:
#include
#defineTRUE1
#defineFALSE0
#defineN10
#defineM2
voidmain(void)
{
doublex[N],y[N],a,l[N];
inti,j,n,flag;
doubleanswer=0.00f;
do{
printf("创建Lagrange插值多项式共用到N组(X,Y)值,请输入N:
");
scanf("%d",&n);
if(n<=N&&n>=M)flag=FALSE;
elseif(n>N||n<=1)
{
printf("对不起,你输入错误!
\n请确保你输入的N满足2<=N<=%d.",N);
printf("\n");
flag=TRUE;
}
}while(flag==TRUE);
printf("\n请输入需要计算的X值:
");
scanf("%lf",&a);
for(i=0;i{
printf("请输入第%d组(X,Y)的值:
",i+1);
scanf("%lf%lf",x+i,y+i);
}
for(i=0;i{
l[i]=1.0f;
for(j=0;jif(i!
=j)l[i]*=(a-x[j])/(x[i]-x[j]);
elsecontinue;
answer+=l[i]*y[i];
}
printf("f(%.3lf)=%lf\n",a,answer);
}
2.2牛顿插值
2.2.1基本原理
构造n次多项式
称为牛顿插值多项式,其中
(二个节点,一阶差商)
(三个节点,二阶差商)
(n+1个节点,n阶差商)
注意:
由于插值多项式的唯一性,有时为了避免拉格朗日余项Rn(x)中n+1阶导数的运算,用牛顿插值公式
,
其中
.
2.2.2优缺点
牛顿插值法具有承袭性和易变性的特点,当增加一个节点时,只要再增加一项就可以了即
而拉格朗日插值若要增加一个节点时全部基函数都需要重新算过。
牛顿插值法既适合于用来计算函数值,也适合于做理论推导,比如说可用来推导微分方程的数值求解公式。
2.2.3数值实验
程序如下:
#include"stdafx.h"
#include
voidmain(intargc,char*argv[])
{inti1,i2,p,j,k,w,n=0;
floatx[100],f[100][100],f1[100],x1,x2,N1,N2=1.0,N3=0.0;
printf("请输入节点个数w<=100:
");
scanf("%d",&w);
for(n=0;n{printf("x=");
scanf("%f",&x[n]);
printf("f(x)=");
scanf("%f",&f1[n]);
}
for(n=0;nf[n][0]=f1[n];
for(j=1;j{k=j;
for(p=0;kf[k][j]=(f[k][j-1]-f[k-1][j-1])/(x[k]-x[p]);
}
printf("xif(xi)1阶差商");
for(i1=1;i1printf("%d阶差商",(i1+1));
for(i1=0;i1{{if(x[i1]>=0)
if(x[i1]>=10&&x[i1]<100)
printf("\n%.5f",x[i1]);
elseif(x[i1]>=100)
printf("\n%.5f",x[i1]);
elseprintf("\n%.5f",x[i1]);
elseif(x[i1]<=-10)
printf("\n%.5f",x[i1]);
elseif(x[i1]<=-100)
printf("\n%.5f",x[i1]);
elseprintf("\n%.5f",x[i1]);
}
for(i2=0;i2<=i1;i2++)
if(f[i1][i2]>=0)
{if(f[i1][i2]>10)
{if(f[i1][i2]>=100)
printf("%.5f",f[i1][i2]);
elseprintf("%.5f",f[i1][i2]);
}
elseprintf("%.5f",f[i1][i2]);
}
else
{if(f[i1][i2]<=-10)
{if(f[i1][i2]<=-100)
printf("%.5f",f[i1][i2]);
elseprintf("%.5f",f[i1][i2]);
}
elseprintf("%.5f",f[i1][i2]);
}
}
printf("\nN%d(x)=%.5f+",n-1,f[0][0]);
for(i1=1;i1for(j=1;jif(i1==j)
{if(f[i1][j]<0)
printf("(%.5f)",f[i1][j]);
elseprintf("%.5f",f[i1][j]);
for(k=0;kprintf("(x-%.5f)",x[k]);
printf("\n");
if(jprintf("+");
}
printf("输入节点x1(用3次多项式计算),
scanf("%f%f",&x1,&x2);
for(i1=0;i1if(x1>x[i1])break;
if((n-i1)>=3)
i2=i1;
else
{i1=i1-2;
if(i1>=0)i2=i1;
else
{i2=i1+1;
i1=i2;
}
}
N1=f[i1][0];
for(j=1;j<4;j++,i1++)
{N2=N2*f[i1+1][i1+1];
for(k=i2;kN2=N2*(x1-x[k]);
N3=N2+N3;
N2=1.0;
}
N3=N1+N3;
printf("N3(%.5f)=%.5f\n",x1,N3);
N3=0.0;
N1=f[0][0];
for(i1=1;i1{for(i2=0;i2N2=N2*(x2-x[i2]);
N2=N2*f[i1][i1];
N3=N2+N3;
N2=1.0;
}
N3=N1+N3;
printf("N%d(%.5f)=%.5f\n",n-1,x2,N3);
}
2.3埃尔米特插值
2.3.1基本原理
设在
个互不相同的节点
处,已知
,
,
.
要求插值多项式
满足:
,
,
.
这类问题与前面的插值问题的区别在于不仅要求在节点上的函数值相等,而且还要求导数也相等,甚至要求高阶导数也相等.求次数不超过
的多项式
使得:
1)
,
.
2)
,
.
类似求Lagrange插值多项式的方法,通过构造基函数的方法.若能够构造出基函数
,
,
满足条件
;
,
.
=
;
,
.
则容易得到
如下:
=
确定基函数
,
:
=
,
.
=
,
.
插值余项
,若
在
内的
阶导数存在,则插值余项
满足
=
,
,其中
且与
有关.
2.3.2优缺点
Hermite插值多项式具有唯一性和承袭性的特点,对相应于条件的
,
的组合形式可以找出尽可能多的条件给出的根,根据多项式的总阶数和根的个数写出表达式,但表达式具有唯一性,可以根据尚未利用的条件解出表达式中的待定系数,在这里待定系数法任适用,但插值节点多时比较麻烦.
2.3.3数值实验
程序如下:
#include
structHINTEP
{
intn;
double*x;
double*y;
double*dy;
doublet;
}hp,ha;
doublehermite(structHINTEP*hp)
{
intnum,i,j;
double*x,*y,*dy,pio,z,p,q,s;
num=hp->n;
x=hp->x;
y=hp->y;
dy=hp->dy;
pio=hp->t;
z=2.0;
for(i=1;i<=num;i++)
{
s=1.0;
for(j=1;j<=num;j++)
if(j!
=i)s*=(pio-x[j-1])/(x[i-1]-x[j-1]);
s=s*s;
p=0.0;
for(j=1;j<=num;j++)
if(j!
=i)p+=1.0/(x[i-1]-x[j-1]);
q=y[i-1]+(pio-x[i-1])*(dy[i-1]-2.0*y[i-1]*p);
z+=q*s;
}
return(z);
}
main()
{
doublex[10]={3.0,5.0,8.0,13.0,17.0,25.0,27.0,29.0,31.0,35.0};
doubley[10]={7.0,10.0,11.0,17.0,23.0,18.0,13.0,6.0,3.0,1.0};
doubledy[10];
inti;
structHINTEPha={10,x,y,dy,19.0};
for(i=0;i<=9;i++)
{
dy[i]=-y[i];
}
printf("\npio=%6.3f,z=%e\n\n",ha.t,hermite(&ha));
}