太原理工大学数值计算实验报告讲解.docx
《太原理工大学数值计算实验报告讲解.docx》由会员分享,可在线阅读,更多相关《太原理工大学数值计算实验报告讲解.docx(19页珍藏版)》请在冰豆网上搜索。
![太原理工大学数值计算实验报告讲解.docx](https://file1.bdocx.com/fileroot1/2023-1/10/e19c2028-88e4-4dbb-a4de-2d5e8587959f/e19c2028-88e4-4dbb-a4de-2d5e8587959f1.gif)
太原理工大学数值计算实验报告讲解
本科实验报告
课程名称:
计算机数值方法
实验项目:
方程求根,线性方程组的直接求解,
线性方程组的迭代求解,代数插值和最小二乘法拟合
实验地点:
软件楼208
专业班级:
学号:
学生姓名:
指导教师:
李志崔冬华
2015年6月5日
学生姓名
实验成绩
实验名称
实验一方程求根
实验内容和要求(必填)
目的:
《数值计算方法》是一门实践性和实用性都很强的课程,学习的目的在于应用已有的理论基础和技术方法,实现对实际计算问题的计算机求解。
本实验配合《计算数值方法》课堂教学,通过上机实践实验环节,巩固课堂和书本上所学的知识、加强实践能力、提高解决实际计算问题的水平、启发创新思想。
其基本目的是:
(1)培养理论联系实际的思路,训练综合运用已经学过的理论和实际知识去分析和解决实际问题的能力。
(2)帮助学生全面消化已学的相关课程内容,深刻理解计算数值方法课程的内涵,培养使用电子计算机进行科学计算和解决问题的能力。
(3)进行基本技能训练和巩固。
使学生得到选择算法、编写程序、分析数值结果、写数值试验报告、课堂讨论等环节的综合训练。
要求:
(1)应用结构化程序设计编出通用程序,源程序要有详细的注释和说明;
(2)比较计算结果,分析数值解误差的原因;
(3)实验完成,要求提交实验结果并写出报告,分析计算结果是否符合问题的要求,找出计算成功的原因或计算失败的教训。
实验原理(必填)
选择上述方法中的两种方法求方程:
f(x)=x3+4x2-10=0在[1,2]内的一个实根,且要求满足精度|x*-xn|<0.5×10-5
主要仪器设备
笔记本计算机
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页)
迭代法:
#include"stdafx.h"
#include"stdio.h"
#include"math.h"
#include"iostream"
usingnamespacestd;
floatmain()
{
floata;
cin>>a;
floatt,x;
x=a;
do{
x=sqrt((10-x*x*x)/4);
t=a;
a=x;
}while(fabs(a-t)>0.5*1e-5);
printf("x=%f",a);
system("pause");
}
割线法:
#include"stdafx.h"
#include"stdio.h"
#include"math.h"
#include"iostream"
usingnamespacestd;
floatmain()
{
floatc,a=1.0,b=2.0;
//cin>>a>>b;
while
(1)
{
c=b-(b*b*b+4*b*b-10)*(b-a)/(b*b*b+4*b*b-(a*a*a+4*a*a));
if(fabs(b-c)<0.5*0.000001)break;
b=c;
}
cout<}
实验结果和分析
实验结果:
迭代法:
割线法:
心得体会(遇到的问题和解决方法)
使用不同的方法,可以不同程度的求得方程的解,不同的方法速度不同。
实验名称
实验二线性方程组的直接求解
实验内容和要求
(1)了解线性方程组常见的直接解法,如Guass消元法、LU分解法、追赶法。
(2)加深对线性方程组求解方法的认识,掌握算法。
(3)会进行误差分析,并能对不同方法进行比较。
实验原理
合理利用Gauss消元法、LU分解法或追赶法求解下列方程组:
1、
2、
3、
4、
(n=5,10,100,…)
主要仪器设备
台式或笔记本计算机
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页)
①Gauss消元法:
#include"stdafx.h"
#include"stdio.h"
#include"iostream"
usingnamespacestd;
floatmain()
{floata[3][4]={{1,2,3,14},{0,1,2,8},{2,4,1,13}};
floatx[3];
floatsum=0;
intk,i,j;
for(k=0;k<2;k++)
for(i=k+1;i<3;i++)
for(j=k+1;j<4;j++)
a[i][j]=a[i][j]-a[i][k]/a[k][k]*a[k][j];
for(i=0;i<3;i++)
for(j=0;j<4;j++)
printf("a[%d][%d]=%f,",i,j,a[i][j]);
cout<x[2]=a[2][3]/a[2][2];
for(k=1;k>=0;k--)
{sum=0;
for(j=k+1;j<3;j++)
{
sum+=a[k][j]*x[j];
}
x[k]=(a[k][3]-sum)/a[k][k];
}
for(i=0;i<3;i++)
printf("x[%d]=%f,",i+1,x[i]);
}
③LU分解法:
#include"stdafx.h"
#include
#include
#defineL30
doublea[L][L],b[L],l[L][L],u[L][L],x[L],y[L];
intmain(){
intn,i,j,k,r;
scanf("%d",&n);
for(i=1;i<=n;++i){
for(j=1;j<=n;++j){
scanf("%lf",&a[i][j]);
}
}
for(i=1;i<=n;++i){
scanf("%lf",&b[i]);
}
for(i=1;i<=n;++i)
{
for(j=1;j<=n;++j)
{
l[i][j]=0;
u[i][j]=0.0;
}
}
for(k=1;k<=n;++k){
for(j=k;j<=n;++j)
{
u[k][j]=a[k][j];
for(r=1;r{
u[k][j]-=l[k][r]*u[r][j];
}
}
for(i=k+1;i<=n;++i){
l[i][k]=a[i][k];
for(r=1;rl[i][k]-=l[i][r]*u[r][k];
}
l[i][k]/=u[k][k];}
l[k][k]=1.0;
}
for(i=1;i<=n;++i){
y[i]=b[i];
for(j=1;j
y[i]-=l[i][j]*y[j];
}
}
for(i=n;i>0;--i){
x[i]=y[i];
for(j=i+1;j<=n;++j){
x[i]-=u[i][j]*x[j];
}x[i]/=u[i][i];
}
for(i=1;i<=n;++i){
printf("%0.2lf\n",x[i]);
}
return0;
}
③追赶法:
#include"stdafx.h"
#include"stdio.h"
voidmain()
{
FILE*f;
doublea[15],b[15],c[15],d[15];
doublet;
inti,n;
f=fopen("zgf.txt","r");
fscanf(f,"%d",&n);
fscanf(f,"%lf%lf%lf",&b[1],&c[1],&d[1]);
for(i=2;i<=n-1;i++)
{
fscanf(f,"%lf%lf%lf%lf",&a[i],&b[i],&c[i],&d[i]);
}
fscanf(f,"%lf%lf%lf",&a[n],&b[n],&d[n]);
fclose(f);
c[1]=c[1]/b[1];
d[1]=d[1]/b[1];
for(i=2;i<=n-1;i++)
{
t=b[i]-c[i-1]*a[i];
c[i]=c[i]/t;
d[i]=(d[i]-d[i-1]*a[i])/t;
}
d[n]=(d[n]-d[n-1]*a[n])/(b[n]-c[n-1]*a[n]);
for(i=n-1;i>=1;i--)d[i]=d[i]-c[i]*d[i+1];
printf("\n********************************\n");
for(i=1;i<=n;i++)
printf("d[%2d]=%lf\n",i,d[i]);
}
Zgf.txt文件中的内容是:
5
21-7
121-5
121-5
121-5
12-5
实验结果和分析
①Gauss消元法:
②
③
心得体会(遇到的问题和解决方法)
在调试过程中发现自己还是很粗心,容易犯简单错误,在今后应该多编写程序。
实验名称
实验三线性方程组的迭代求解
实验内容和要求
学习使用雅可比迭代法或高斯-赛德尔迭代法
实验原理
主要仪器设备
台式或笔记本计算机
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页)
高斯-赛德尔迭代法:
#include"stdafx.h"
#include"stdio.h"
#include"math.h"
voidmain()
{
floata[3][3]={{10,-1,-2},{-1,10,-2},{-1,-1,5}},b[3]={7.2,8.3,4.2};
floatx[3]={0,0,0},sum1,sum2;
inti,j,k,n=3;
for(k=0;k<10;k++)
{for(i=0;i{
sum1=0;
sum2=0;
for(j=0;j
{
sum1=sum1+a[i][j]*x[j];}
for(j=i+1;j<3;j++)
{
sum2=sum2+a[i][j]*x[j];
}
x[i]=(b[i]-sum1-sum2)/a[i][i];
for(i=0;i{printf("x[%d]=%f,",i+1,x[i]);
printf("\n");
}
}
}
}
雅克比迭代:
#include"stdafx.h"
#include
#include
voidmain()
{
floata[3][3]={{10,-1,-2},{-1,10,-2},{-1,-1,5}},b[3]={7.2,8.3,4.2};
floatx[3]={0,0,0},sum1;
inti,j,k,n=3;
for(k=0;k<10;k++)
{
for(i=0;i<3;i++)
{
sum1=0;
for(j=0;j{if(i==j)continue;
sum1=sum1+a[i][j]*x[j];
}
x[i]=(b[i]-sum1)/a[i][i];
}
for(i=0;i{printf("x[%d]=%f,",i+1,x[i]);}
printf("\n");
}
}
实验结果和分析
结果:
高斯-赛德尔迭代法:
雅克比迭代:
分析:
使用高斯-赛德尔和雅克比迭代都可以求出方程组的解,但是利用高斯-赛德尔迭代法所需的迭代次数比雅克比迭代少,能够更早的达到精度要求。
心得体会(遇到的问题和解决方法)
高斯迭代法比雅克比迭代迭代速度快,所以在编程时选择了高斯迭代法。
实验名称
实验四代数插值和最小二乘法拟合
实验内容和要求
实验内容:
使用拉格朗日插值法求解:
已知f(x)在6个点的函数值如下表所示,运用插值方法,求f(0.596)的近似值。
x
0.40
0.55
0.65
0.80
0.90
1.05
f(x)
0.41075
0.57815
0.69675
0.88811
1.02652
1.25386
实验要求:
1.了解拉格朗日插值法的基本方法、基本原理。
2.通过编写程序,进行算法设计和数值求解。
实验原理
拉格朗日基函数为:
拉格朗日插值多项式为:
主要仪器设备
台式或笔记本计算机
实验记录(写出实验内容中的程序代码和运行结果)(可分栏或加页)
#include
#include
#include
typedefstructdata
{
floatx;
floaty;
}Data;
Datad[20];
floatf(ints,intt)
{
if(t==s+1)
return(d[t].y-d[s].y)/(d[t].x-d[s].x);
else
return(f(s+1,t)-f(s,t-1))/(d[t].x-d[s].x);
}
floatNewton(floatx,intcount)
{
intn;
while
(1)
{
cout<<"请输入n值(即n次插值):
";
cin>>n;
if(n<=count-1)
break;
else
system("cls");
}
floatt=1.0;
floaty=d[0].y;
floatyt=0.0;
for(intj=1;j<=n;j++)
{
t=(x-d[j-1].x)*t;
yt=f(0,j)*t;
y=y+yt;
}
returny;
}
floatlagrange(floatx,intcount)
{
floaty=0.0;
for(intk=0;k{
floatp=1.0;
for(intj=0;j{
if(k==j)continue;
p=p*(x-d[j].x)/(d[k].x-d[j].x);
}
y=y+p*d[k].y;
}
returny;
}
voidmain()
{
floatx,y;
intcount;
while
(1)
{
cout<<"请输入x[i],y[i]的组数,不得超过20组:
";
cin>>count;
if(count<=20)
break;
system("cls");
}
for(inti=0;i{
cout<<"请输入第"<
";
cin>>d[i].x;
cout<<"请输入第"<
";
cin>>d[i].y;
system("cls");
}
cout<<"请输入x的值:
";//获得变量x的值
cin>>x;
while
(1)
{
intchoice=3;
cout<<"请您选择使用哪种插值法计算:
"<cout<<"(0):
退出"<cout<<"
(1):
Lagrange"<cout<<"
(2):
Newton"<cout<<"输入你的选择:
";
cin>>choice;
if(choice==2)
{
cout<<"你选择了牛顿插值计算方法,其结果为:
";
y=Newton(x,count);break;
}
if(choice==1)
{
cout<<"你选择了拉格朗日插值计算方法,其结果为:
";
y=lagrange(x,count);break;
}
if(choice==0)
break;
system("cls");
cout<<"输入错误!
!
!
!
"<}
cout<}
实验结果和分析
分析:
拉格朗日插值的优点是插值多项式特别容易建立,缺点是增加节点是原有多项式不能利用,必须重新建立,即所有基函数都要重新计算,这就造成计算量的浪费。
心得体会(遇到的问题和解决方法)