数值分析试验.docx
- 文档编号:15748825
- 上传时间:2023-07-07
- 格式:DOCX
- 页数:35
- 大小:474.22KB
数值分析试验.docx
《数值分析试验.docx》由会员分享,可在线阅读,更多相关《数值分析试验.docx(35页珍藏版)》请在冰点文库上搜索。
数值分析试验
实验一:
拉格朗日插值法
一、实验目的
1、理解龙拉格朗日插值的方法原理;
2、利用拉格朗日插值法拟合插值多项式。
二、实验步骤
1、拉格朗日插值原理
在求满足插值条件n次插值多项式Pn(x)之前,先考虑一个简单的插值问题:
对节点
中任一点Xk做一
次多项式
,使它在该点上取值为1,而在其余点
上取值为零,即
上式表明n个点
都是n次多项式
的零点,故可设:
其中,Ak为待定系数。
由条件
=1立即可得
故
由上式可以写出n1个n次插值多项式
。
我们称它们为在n+1个节点
上的n次基本插值多项式或n次插值基函数。
利用插值基函数立即可以写出满足插值条件的n次插值多项式
根据条件
容易验证上面多项式在节点xi处的值为yi因此,它就是待求的n次插值多项式Pn(x)。
形如
的插值多项式就是拉格朗日插值多项式,记为
Ln(x),即
作为常用的特例,令n+1,由上式即得两点插值公式
这是一个线性函数,故又名线性插值。
2.流程图
3.例题
已给sin0.32=0.314567,sin0.34=0.333487,sin0.36=0.352274,计算sin0.3367的值
3、程序代码
#include
#include
#include
usingnamespacestd;
intmain()
{inti,j;
doublenumerator_cofficient;//用来记录插值分子的乘积结果
doubledenominator_coefficient;//用来记录插值分母乘积的结果
doubleinput_x;//需要输入的x的值
doublex[3]={0.32,0.34,0.36};//已知x的值
doubley[3]={0.314567,0.333487,0.352274};//已知y的值
doubleresult=0;//用来记录插值结果
cout<<"通过拟合得到的拉格朗日多项式为:
"< for(i=0;i<3;i++) { denominator_coefficient=1; cout< for(j=0;j<3;j++) { if(i==j) continue; cout<<"("<<"x-"< } cout<<"/"; for(j=0;j<3;j++) { if(i==j) continue; denominator_coefficient*=(x[i]-x[j]); } cout< if(i<3) { cout<<"+"; } } cout< cout<<"请输入需要插值的x: "; cin>>input_x; for(i=0;i<3;i++) { numerator_cofficient=1; denominator_coefficient=1; for(j=0;j<3;j++) { if(i==j) continue; numerator_cofficient*=(input_x-x[j]); } for(j=0;j<3;j++) { if(i==j) continue; denominator_coefficient*=(x[i]-x[j]); } result+=(y[i]*numerator_cofficient/denominator_coefficient); } cout<<"插值结果为: "< : fixed)< cout<<"函数的真实值: "< cout<<"计算误差为: "<<(result-sin(0.3367))/sin(0.3367)*100<<"%"< return0; } 4、运行结果 实验二: 龙贝格求积公式 一、实验目的 1、理解龙贝格求积公式的方法原理; 2、利用龙贝格求积公式计算积分。 二、实验步骤 龙贝格算法是由递推算法得来的。 由梯形公式得出辛普生公式得出柯特斯公式最后得到龙贝格公式。 在变步长的过程中探讨梯形法的计算规律。 设将求积区间[a,b]分为n个等 分,则一共有n+1个等分点 复化梯形法求得的积分值,其下标n表示等分数。 先考察下一个字段 在该子段上二分前后两个积分值 显然有下列关系 将这一关系式关于k从0到n-1累加求和,即可导出下列递推公式: 需要强调指出的是,上式中的 代表二分前的步长,而 梯形法的算法简单,但精度低,收敛速度缓慢,如何提高收敛速度以节省计 算量,自然式人们极为关心的。 根据梯形法的误差公式,积分值Tn的截断误差大致与 成正比,因此步长减半后误差将减至四分之一,既有 将上式移项整理,知 由此可见,只要二分前后两个积分值Tn和T2n相当接近,就可以保证计算保证结果计算结果T2n的误差很小,这种直接用计算结果来估计误差的方法称作误差的事后估计法。 按上式,积分值T2n的误差大致等于1/3(T2n-Tn),如果用这个误差值作为T2n的一种补偿,可以期望,所得的 应当是更好的结果。 按上式,组合得到的近似值T直接验证,用梯形二分前后的两个积分值Tn和T2n按 式组合,结果得到辛普生法的积分值Sn。 再考察辛普生法。 其截断误差与4h成正比。 因此,若将步长折半,则误差相 应的减至十六分之一。 既有 » - 不难验证,上式右端的值其实就等于nC,就是说,用辛普生法二分前后的两个积分值 Sn和S2n,在按上式再做线性组合,结果得到柯特斯法的积分值Cn,既有 重复同样的手续,依据斯科特法的误差公式可进一步导出龙贝格公式 应当注意龙贝格公式已经不属于牛顿—柯特斯公式的范畴。 在步长二分的过程中运用公式加工三次,就能将粗糙的积分值Tn逐步加工成精度较高的龙贝格Rn,或者说,将收敛缓慢的梯形值序列Tn加工成熟练迅速的龙贝格值序列Rn,这种加速方法称龙贝格算法。 2.算法步骤,流程图 3.例题 3、程序代码 #include #include #include #include usingnamespacestd; intpower(inta,intb) {intresult=1; if(b==0) returnresult; while(b! =0) { result*=a; b--; } returnresult; } intmain() { intM=5;//M表示二分的次数 inti,j,k; double**T=newdouble*[M+1]; for(i=0;i T[i]=newdouble[i+1]; doublea=0,b=1;//a表示积分下限,b表示积分上限 doublefa=pow(a,1.5),fb=pow(b,1.5);//fa表示在a点处被积函数的函数值,fb表示在b点处被积函数的函数值 doubleh=b-a;//h表示迭代的步长 doublesum;//用于计算积分内循环累加的部分 T[0][0]=(fa+fb)*h/2;//用梯形公式进行初始化 for(i=1;i { h/=2; sum=0; for(j=1;j<=power(2,i-1);j++) sum+=pow(a+(2*j-1)*h,1.5);//计算产生的新的结点部分的和 T[i][0]=T[i-1][0]/2+h*sum;//利用原来计算得到的积分值和新的节点计算得到新的积分值 for(k=1;k<=i;k++) T[i][k]=T[i][k-1]+(T[i][k-1]-T[i-1][k-1])/(power(4,k)-1);//利用龙贝格积分公式计算后面的积分 } cout< : left) < < < < < < for(i=0;i {for(j=0;j<=i;j++) cout< cout< } cout< cout<<"最后计算得到的积分值为"< for(i=0;i delete[]T[i]; delete[]T; return0; } 四、心得体会 通过本次试验,我理解了龙贝格求积分方法的原理,并且能利用龙贝格求积公式式计算积分,在数值分析的理论知识上又有了较大的收获,在进行编程的过程中,我已经基本熟练了数值算法的程序过程,能独立的在有限的时间内完成,这对以后的学习会有很大的帮助,另外对复习这一块的知识也起到了很大的帮助。 实验三: 线性方程组求解 一、实验目的 1、理解雅克比迭代,高斯赛德迭代,超松弛迭代的方法原理; 2、分析三种算法的结果,分析各算法的特点。 二、实验内容 1.解方程组 算法一: 雅克比迭代 优点: 算法简单,编制程序比较容易 缺点: 他要求的系数矩阵具有某种特殊性质,以保证迭代过程的收敛性。 ※流程图 ※程序代码 #include #defineN10 floatABS(float,float); int main(void) { inti,j,n; floata[N][N],b[N]; floatx[N],y[N]; floate,total; printf("Pleaseinputthedimension: "); scanf("%d",&n); printf("PleaseinputtheCoefficientMatrix: "); for(i=0;i for(j=0;j scanf("%f",&a[i][j]); printf("PleaseinputtheVector: "); for(i=0;i scanf("%f",&b[i]); printf("Pleaseinputtheinitialvector: "); for(i=0;i scanf("%f",&x[i]); do { for(i=0;i { total=0.0f; for(j=0;j { if(i! =j) total+=a[i][j]*x[j]; } y[i]=(b[i]-total)/a[i][i]; } e=0.0f; for(j=0;j e=e+ABS(x[j],y[j]); printf("%f\n",e); for(i=0;i x[i]=y[i]; } while(e>0.0001); for(i=0;i printf("x%d=%f\t",i,x[i]); printf("\n"); return0; } floatABS(floatx,floaty) { inttotal; if(x elsetotal=x-y; returntotal; } ※结果: 方法二: 高斯赛德迭代 ※流程图 ※程序代码 #include"iostream.h" #include #include #include #defineM10 intn; voidGS(doublex[],doublex0[],doublea[][M],doubleb[],doubleeps,intNmax) { inti,j,s=0; doublemax; while(s { for(i=0;i { x[i]=b[i]; for(j=0;j if(j! =i) x[i]=x[i]-a[i][j]*x[j]; x[i]=x[i]/a[i][i]; } max=fabs(x[0]-x0[0]); for(i=1;i if(fabs(x[i]-x0[i])>max) max=fabs(x[i]-x0[i]); if(max break; for(i=0;i x0[i]=x[i]; s++; } printf("迭代次数为: %d\n",s); if(s>=Nmax) cout<<"迭代发散! \n"< else {cout<<"原方程的解为: \n"< for(i=0;i printf("x%d=%f\n",i+1,x[i]); } } voidmain() { doublea[10][10]={{5,2,1},{-1,4,2},{2,-3,10}}; doubleb[10]={-12,20,3}; doublex[10],x01[10]; doubleeps; inti,j,s=0,Nmax=10; cout<<"请输入系数矩阵: "< n=3; for(i=0;i { for(j=0;j cout< cout< } cout<<"输入初始值: "< for(i=0;i {printf("x%d=",i+1); cin>>x[i]; x01[i]=x[i]; } cout<<"\n输入所需精度: "< cin>>eps; GS(x,x01,a,b,eps,Nmax); } ※结果 算法三: 超松弛迭代 ※流程图 ※程序代码 #include #include usingnamespacestd; float*one_array_malloc(intn); float**two_array_malloc(intm,intn); floatmatrix_category(float*x,intn); intmain() {constintMAX=100; intn,i,j,k;float**a;float*x_0; float*x_k; floatprecision;floatw; cout<<"输入精度e: "; cin>>precision; cout< "; cin>>n;a=two_array_malloc(n,n+1); cout< \n"; for(i=0;i { for(j=0;j {cin>>a[i][j];} } x_0=one_array_malloc(n); cout< \n"; for(i=0;i {cin>>x_0[i];} x_k=one_array_malloc(n); cout<<"输入松弛因子w(1 \n"; cin>>w; floattemp; for(k=0;k {for(i=0;i {temp=0; for(j=0;j {temp=temp+a[i][j]*x_k[j];} x_k[i]=a[i][n]-temp; temp=0; for(j=i+1;j {temp=temp+a[i][j]*x_0[j];} x_k[i]=(x_k[i]-temp)/a[i][i]; x_k[i]=(1-w)*x_0[i]+w*x_k[i];} for(i=0;i {x_0[i]=x_k[i]-x_0[i];} if(matrix_category(x_0,n) {break;} else{for(i=0;i {x_0[i]=x_k[i];} } } if(MAX==k) {cout<<"迭代不收敛\n";} cout<<"迭代次数为: "< cout<<"解向量为: \n"; for(i=0;i {cout<<"x"< "< return0; } float*one_array_malloc(intn) {float*a; a=(float*)malloc(sizeof(float)*n); returna; } float**two_array_malloc(intm,intn) {float**a; inti; a=(float**)malloc(m*sizeof(float*)); for(i=0;i {a[i]=(float*)malloc(n*sizeof(float));} returna; } floatmatrix_category(float*x,intn) {inti;floattemp=0;for(i=0;i {temp=temp+fabs(x[i]);} returntemp; } ※结果 三、实验结果分析 三种算法的比较分析 由计算结果来分析: 方程的精确解为-4,3,2,利用雅克比迭代的方法结果为-3.991400,2.627500,2.034700迭代四次,结果偏离真实值较大,精度不高。 利用高斯赛德方法迭代,当精度达到e=0.0001时,需要迭代7次,迭代的结果为-4.000033,2.999983,2.000003,精度相对于雅克比迭代高出很多,另外,超松弛迭代,当松弛因子W=1时,精度e=0.0001时,迭代8次,迭代结果为-3.99999,3,2,迭代出现了两个精确值。 通过迭代精度迭代结果的计较而得,超松弛迭代相对于雅克比,高斯赛德迭代好得多,但是迭代次数较多,在数据处理的过程中根据精度不同,选择不同的迭代方法。 实验四: 微分方程求解 一、实验目的 1、理解欧拉法,改进欧拉法,四阶经典龙格库塔法的原理; 2、分析三种算法的结果,分析各算法的特点。 二、实验内容 例2: 算法一: 欧拉法 ※流程图 ※程序代码 #include #include #include #include usingnamespacestd; intmain() {doublex,y,h; x=0; y=1; h=0.1; cout< : left); cout< cout< cout< cout< cout< cout< cout< cout< for(inti=0;i<10;i++) { x+=h; cout< y=y+h*(y-(2*x/y)); cout< cout< cout< } return0; } ※结果 方法二: 改进欧拉法 ※流程图 ※程序代码 #include #include #include #include usingnamespacestd; intmain() { doublex,y,h,temp,f; x=0; y=1; h=0.1; cout< : left); cout< cout< cout< cout< cout< cout< cout< cout< for(inti=0;i<10;i++) {temp=y; f=y-(2*x/y); y=y+h*(y-(2*x/y)); x+=h; y=temp+h/2
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数值 分析 试验
![提示](https://static.bingdoc.com/images/bang_tan.gif)