计算方法实验报告汇总.docx

上传人:b****3 文档编号:4465976 上传时间:2022-12-01 格式:DOCX 页数:51 大小:645.86KB
下载 相关 举报
计算方法实验报告汇总.docx_第1页
第1页 / 共51页
计算方法实验报告汇总.docx_第2页
第2页 / 共51页
计算方法实验报告汇总.docx_第3页
第3页 / 共51页
计算方法实验报告汇总.docx_第4页
第4页 / 共51页
计算方法实验报告汇总.docx_第5页
第5页 / 共51页
点击查看更多>>
下载资源
资源描述

计算方法实验报告汇总.docx

《计算方法实验报告汇总.docx》由会员分享,可在线阅读,更多相关《计算方法实验报告汇总.docx(51页珍藏版)》请在冰豆网上搜索。

计算方法实验报告汇总.docx

计算方法实验报告汇总

 

中南林业科技大学

计算机与信息工程学院

《数值分析》

实验报告

姓名:

尹一君__

学号:

20134651

指导老师:

赵红敏

专业班级:

计算机科学与技术2班

指导教师评语:

成绩:

 

签名:

年月日

实验一算法设计基础-2-

实验二非线性方程求根-6-

实验三线性方程组的直接解法-13-

实验四解线性方程组的迭代法-21-

实验五函数插值方法-27-

实验六函数逼近与曲线拟合-31-

实验七数值积分与数值微分-36-

参考文献-42-

 

实验一算法设计基础

1.问题提出

编程实现以下矩阵相乘:

2.要求

1.编织一个程序进行运算,最后打印出结果;

2.将编程结果与手工演算结果进行比较;

3.原始数据使用ASCII码数据文件的形式访问;

4.最好能将程序结果输出到ASCII码数据文件。

3.实验目的和意义

1.通过实验进一步熟悉矩阵运算和多重循环编程;

2.熟悉数据文件访问操作。

四.计算公式

在计算机中,一个矩阵实际上就是一个二维数组。

一个m行n列的矩阵与一个n行p列的矩阵可以相乘,得到的结果是一个m行p列的矩阵,其中的第i行第j列位置上的数为第一个矩阵第i行上的n个数与第二个矩阵第j列上的n个数对应相乘后所得的n个乘积之和。

五.结构程序设计

1.

#defineM4

#defineN3

#defineL3

#include"stdio.h"

voidmain()

{

FILE*f;

floatA[M][L],B[L][N],C[M][N];

inti,j,k;

if((f=fopen("Array1.txt","r"))==NULL)

return;

for(i=0;i

for(j=0;j

fscanf(f,"%f",&A[i][j]);

for(i=0;i

for(j=0;j

fscanf(f,"%f",&B[i][j]);

for(i=0;i

{

for(j=0;j

{

C[i][j]=0;

for(k=0;k

C[i][j]=C[i][j]+A[i][k]*B[k][j];

printf("%10.2f",C[i][j]);

}

printf("\n");

}

}

 

2.

#defineM2

#defineN3

#defineL4

#include"stdio.h"

voidmain()

{

FILE*f1;

intA[M][L],B[L][N],C[M][N];

inti,j,k;

if((f1=fopen("Array2.txt","r"))==NULL)

return;

for(i=0;i

for(j=0;j

fscanf(f1,"%d",&A[i][j]);

for(i=0;i

for(j=0;j

fscanf(f1,"%d",&B[i][j]);

for(i=0;i

{

for(j=0;j

{

C[i][j]=0;

for(k=0;k

C[i][j]=C[i][j]+A[i][k]*B[k][j];

printf("%4d",C[i][j]);

}

printf("\n");

}

}

 

六.结果展示

程序1和2的运行结果分别如图1-1和1-2所示:

图1-1图1-2

七.实验讨论与总结

1.本实验考察了对数据文件的建立、读入和试用,是一个突破;

2.第一个矩阵相乘中出现小数,故应用float数据类型;第二个矩阵中全是整数,故用int型即可。

3.对于输出结果的排版需要格外注意,应灵活使用输出格式符使其美观完整。

4.文件操作的基本函数(打开、关闭、输入和输出)

①fopen(打开文件)

相关函数open,fclose

表头文件#include

定义函数FILE*fopen(constchar*path,constchar*mode);

函数说明参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。

②fclose(关闭文件)

相关函数close,fflush,fopen,setbuf

表头文件#include

定义函数intfclose(FILE*stream);

函数说明fclose()用来关闭先前fopen()打开的文件。

此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。

返回值若关文件动作成功则返回0,有错误发生时则返回EOF并把错误代码存到errno。

错误代码EBADF表示参数stream非已打开的文件。

③fscanf(输入函数)

功能:

从一个流中执行格式化输入

表头文件:

#include

函数原型:

intfscanf(FILE*stream,char*format[,argument...]);

FILE*一个FILE型的指针

char*格式化输出函数,和scanf里的格式一样

返回值:

成功时返回转换的字节数,失败时返回一个负数

fp=fopen("/local/test.c","a+");

fscanf(fp,"%s",str);

④fprintf

功能:

传送格式化输出到一个文件中

表头文件:

#include

函数原型:

intfprintf(FILE*stream,char*format[,argument,...]);

FILE*一个FILE型的指针

char*格式化输入函数,和printf里的格式一样

返回值:

成功时返回转换的字节数,失败时返回一个负数

fp=fopen("/local/test.c","a+");

fprintf(fp,"%s\n",str)

实验二非线性方程求根

1.问题提出

二.要求

1.编制一个程序进行运算,最后打印出每种迭代格式的敛散情况;

2.用事后误差估计|xk+1-xk|<ε来控制迭代次数,并且打印出迭代的次数;

3.初始值的选取对迭代收敛有何影响;

4.分析迭代收敛和发散的原因。

三.实验目的和意义

1.通过实验进一步了解方程求根的算法;

2.认识选择计算格式的重要性;

3.掌握迭代算法和精度控制;

4.明确迭代收敛性与初值选取的关系。

四.计算公式

对于给定的线性方程组x=Bx+f(这里的xBf同为矩阵,任意线性方程组都可以变换成此形式),用公式x(k+1)=Bx(k)+f(括号中为上标,代表迭代k次得到的x,初始时k=0)逐步带入求近似解的方法称为迭代法(或称一阶定常迭代法)。

如果k趋向无穷大时limx(k)存在,记为x*,称此迭代法收敛。

显然x*就是此方程组的解,否则称为迭代法发散。

五.结构程序设计

各函数及其导数建立如图2-1和图2-2所示:

 

图2-1图2-2

 

主函数如下:

voidmain()

{

doublei,j;

doubleeps=1e-10;

intk;

if(fabs(f11

(1))>1||fabs(f11

(2))>1)

printf("不满足收敛条件\n");

else

{

k=0;

i=f1

(1);j=i;i=f1(j);

while(fabs(i-j)>eps)

{

j=i;

i=f1(j);k++;

}

printf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

if(fabs(f22

(1))>1||fabs(f22

(2))>1)

printf("不满足收敛条件\n");

else

{

k=0;

i=f2

(1);j=i;i=f2(j);

while(fabs(i-j)>eps)

{

j=i;

i=f2(j);k++;

}

printf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

if(fabs(f33

(1))>1||fabs(f33

(2))>1)

printf("不满足收敛条件\n");

else

{

k=0;

i=f3

(1);j=i;i=f3(j);

while(fabs(i-j)>eps)

{

j=i;

i=f3(j);k++;

}

printf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

if(fabs(f44

(1))>1||fabs(f44

(2))>1)

printf("不满足收敛条件\n");

else

{

k=0;

i=f4

(1);j=i;i=f4(j);

while(fabs(i-j)>eps)

{

j=i;

i=f4(j);k++;

}

printf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

if(fabs(f55

(1))>1||fabs(f55

(2))>1)

printf("不满足收敛条件\n");

else

{

k=0;

i=f5

(1);j=i;i=f5(j);

while(fabs(i-j)>eps)

{

j=i;

i=f5(j);k++;

}

printf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

if(fabs(f66

(1))>1||fabs(f66

(2))>1)

printf("不满足收敛条件\n");

else

{

k=0;

i=f6

(1);j=i;i=f6(j);

while(fabs(i-j)>eps)

{

j=i;

i=f6(j);k++;

}

printf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

}

五.结果展示

程序运行结果如图2-3所示:

 

图2-3

六.实验讨论与总结

1.完成本实验相当于实现了将迭代算法转化成程序语言这一突破;

2.本实验考察众多容易忽视的细节和学生的仔细程度,比如六个函数转化成C语言时,语法会出现众多不适,括号较多,很容易出错;另一方面,在用pow函数求x的y次方时,容易将x的1/3次方写成pow(x,1/3),这样写是错误的。

因为1/3为两int型整数相除,系统执行结果为0,故应写成pow(x,1.0/3)。

这是一个极容易忽视的地方;

☆3.方法改进

由于求导法判定迭代收敛时,必定限制在一个区间内,而这个区间内只能存在一个根。

因此用该方法判断出来的迭代结果如果是不收敛,并不能说明它对于其余的根也不收敛。

因此,求导法只能求出f(x)的一个根,不能满足题目要求,而且求导需人工执行、过程繁琐。

故对该算法进行改进:

#include"math.h"

#include"stdio.h"

doublef1(doublex)

{return((3*x+1)/(x*x));}

doublef2(doublex)

{return((pow(x,3)-1)/3);}

doublef3(doublex)

{return(pow(3*x+1,1.0/3));}

doublef4(doublex)

{return(1/(x*x-3));}

doublef5(doublex)

{return(pow((3+1/x),1.0/2));}

doublef6(doublex)

{return(x-(x*x*x-3*x-1)/(3*(x*x-1)));}//无需建立导函数

voidmain()

{

doublei,j;

doubleeps=1e-5;

intk;

k=0;

i=f1

(1);j=i;i=f1(j);

while(fabs(i-j)>eps)

{

j=i;

i=f1(j);k++;

}

if(i<-99999)printf("不满足收敛条件\n");

elseprintf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

k=0;

i=f2

(1);j=i;i=f2(j);

while(fabs(i-j)>eps)

{

j=i;

i=f2(j);k++;

}

if(i<-99999)printf("不满足收敛条件\n");

elseprintf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

k=0;

i=f3

(1);j=i;i=f3(j);

while(fabs(i-j)>eps)

{

j=i;

i=f3(j);k++;

}

if(i<-99999)printf("不满足收敛条件\n");

elseprintf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

k=0;

i=f4

(1);j=i;i=f4(j);

while(fabs(i-j)>eps)

{

j=i;

i=f4(j);k++;

}

if(i<-99999)printf("不满足收敛条件\n");

elseprintf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

k=0;

i=f5

(1);j=i;i=f5(j);

while(fabs(i-j)>eps)

{

j=i;

i=f5(j);k++;

}

if(i<-99999)printf("不满足收敛条件\n");

elseprintf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

k=0;

i=f6

(1);j=i;i=f6(j);

while(fabs(i-j)>eps)

{

j=i;

i=f6(j);k++;

}

if(i<-99999)printf("不满足收敛条件\n");

elseprintf("满足收敛条件,x≈%f,迭代次数为%d次\n",i,k);

}

改进算法的程序运行结果如图2-4所示:

 

图2-4

该方法的思想是:

无区间限制迭代,如果迭代结束得到的结果为无穷大或无穷小,则说明该迭代不收敛。

这种做法更加实用,而且可以看出,求得了两个根。

但就科学性而言,教材上定理2.1的内容显示了迭代法收敛的条件。

定义明确指出用求导判断收敛性,根据定义判断才是最科学的方法。

但考虑到计算机语言的便利性就在于全过程无人工计算,而手动求导的方法与之相违背,从这个角度考虑,改进法更加具有说服力。

但若只需求一个根而又要讲究科学性,我们仍然可以选择求导法。

因此,我们应做到根据情况的不同来选择不同的适当方法来解决问题。

4.初始值的选取对迭代收敛有何影响?

初始值的选取虽然不会改变迭代收敛的性质,但是会影响其收敛速度。

为了提高收敛速度,可设法提高初值的精度以减少迭代的次数。

5.分析迭代收敛和发散的原因。

迭代公式收敛与否,完全取决于迭代公式ψ(x)的性态。

这里考察到迭代法的几何意义:

方程x=ψ(x)的求根问题在几何上就是确定曲线y=ψ(x)与直线y=x的交点P的横坐标。

按教材图2.3演示的路径走下去,在曲线y=ψ(x)上得到点列P0,P1,…,其横坐标分别按迭代公式所确定的迭代值x1,x2,…,如果迭代收敛,则点P1,P2,…将越来越逼近所求的交点P。

否则迭代法发散。

这是迭代收敛和发散的本质原因。

 

实验三线性方程组的直接解法

1.问题提出

给出下列几个不同类型的线性方程组,请用适当算法计算其解。

 

 

 

二.要求

1.对上述三个方程组分别利用Gauss顺序消去法与Gauss列主元消去法;平方根法与改进平方根法;追赶法求解(选择其一);

2.应用结构程序设计编出通用程序;

3.比较计算结果,分析数值解误差的原因;

4.尽可能利用相应模块输出系数矩阵的三角分解式。

三.实验目的和意义

1.通过该课题的实验,体会模块化结构程序设计方法的优点;

2.运用所学的计算方法,解决各类线性方程组的直接算法;

3.提高分析和解决问题的能力,做到学以致用;

4.通过三对角形线性方程组的解法,体会稀疏线性方程组解法的特点。

四.计算公式

本次实验的三个方程组,在此分别使用Gauss顺序消去法、平方根法和追赶法求解。

下面给出这三种方法的计算公式。

1.Gauss顺序消去法计算公式

 

2.平方根法计算公式

3.追赶法计算公式

 

五.结构程序设计

1.用Gauss顺序消去法求解线性方程组的程序设计如下(问题1):

//Gauss顺序消去法--求解线性方程组

//设计人:

尹一君20134651

#include"stdio.h"

#include"math.h"

voidmain()

{

FILE*f;

doublea[20][20],b[20],x[20];

doublem,s;

inti,j,k;

if((f=fopen("Array3.txt","r"))==NULL)

return;

for(i=1;i<=10;i++)

for(j=1;j<=10;j++)

fscanf(f,"%lf",&a[i][j]);

for(i=1;i<=10;i++)

fscanf(f,"%lf",&b[i]);

fclose(f);

for(k=1;k<10;k++)

for(i=k+1;i<=10;i++)

{

for(j=k+1;j<=10;j++)

{

m=a[i][k]/a[k][k];

a[i][j]=a[i][j]-m*a[k][j];

}

b[i]=b[i]-m*b[k];

}

x[10]=b[10]/a[10][10];

for(i=9;i>0;i--)

{

s=0;

for(j=i+1;j<=10;j++)

s=s+a[i][j]*x[j];

x[i]=(b[i]-s)/a[i][i];

}

for(i=1;i<=10;i++)

{

if(fabs(x[i])<0.5)

x[i]=fabs(x[i]);

printf("x[%d]=%f\n",i,x[i]);

}

}

 

2.用平方根法求解对称正定阵系数阵线方程组的程序设计如下(问题2):

//平方根法--求解对称正定阵系数阵线方程组

//设计人:

尹一君20134651

#include"stdio.h"

#include"math.h"

voidmain()

{

FILE*f;

doublea[10][10],b[10],l[10][10],x[10],y[10];

doubles1,s2,s3,s4;

inti,j,k;

if((f=fopen("Array4.txt","r"))==NULL)

return;

for(i=1;i<=8;i++)

for(j=1;j<=8;j++)

fscanf(f,"%lf",&a[i][j]);

for(i=1;i<=8;i++)

fscanf(f,"%lf",&b[i]);

fclose(f);

l[1][1]=pow(a[1][1],1.0/2);

for(i=1,j=2;j<=8;j++)

l[j][i]=a[j][i]/l[1][1];

for(i=2;i<=8;i++)

for(j=i;j<=8;j++)

if(i==j)

{

s1=0;

for(k=1;k<=i-1;k++)

s1=s1+l[i][k]*l[i][k];

l[i][i]=pow((a[i][i]-s1),1.0/2);

}

else

{

s2=0;

for(k=1;k<=i-1;k++)

s2=s2+l[j][k]*l[i][k];

l[j][i]=(a[j][i]-s2)/l[i][i];

}

y[1]=b[1]/l[1][1];

for(i=2;i<=8;i++)

{

s3=0;

for(k=1;k<=i-1;k++)

s3=s3+l[i][k]*y[k];

y[i]=(b[i]-s3)/l[i][i];

}

x[8]=y[8]/l[8][8];

for(i=7;i>=1;i--)

{

s4=0;

for(k=i+1;k<=8;k++)

s4=s4+l[k][i]*x[k];

x[i]=(y[i]-s4)/l[i][i];

}

for(i=1;i<=8;i++)

{

if(fabs(x[i])<0.5)

x[i]=fabs(x[i]);

printf("x[%d]=%f\n",i,x[i]);

}

}

 

3.用追赶法求解三对角形线性方程组的程序设计如下(问题3):

//追赶法--求解三对角形线性方程组

//设计人:

尹一君20134651

#include"stdio.h"

#include"math.h"

voidmain()

{

FILE*p;

doublea[15],b[15],c[15],f[15],l[15],u[15],x[15],y[15];

inti;

if((p=fopen("Array5.txt","r"))==NULL)

return;

for(i=1;i<=10;i++)

fscanf(p,"%lf",&a[i]);

for(i=1;i<=10;i++)

fscanf(p,"%lf",&b[i]);

for(i=1;i<=10;i++)

fscanf(p,"%lf",&c[i]);

for(i=1;i<=10;i++)

fscanf(p,"%lf",&f[i]);

fclos

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1