数值分析上机题答案.docx

上传人:b****8 文档编号:10224713 上传时间:2023-02-09 格式:DOCX 页数:42 大小:95.87KB
下载 相关 举报
数值分析上机题答案.docx_第1页
第1页 / 共42页
数值分析上机题答案.docx_第2页
第2页 / 共42页
数值分析上机题答案.docx_第3页
第3页 / 共42页
数值分析上机题答案.docx_第4页
第4页 / 共42页
数值分析上机题答案.docx_第5页
第5页 / 共42页
点击查看更多>>
下载资源
资源描述

数值分析上机题答案.docx

《数值分析上机题答案.docx》由会员分享,可在线阅读,更多相关《数值分析上机题答案.docx(42页珍藏版)》请在冰豆网上搜索。

数值分析上机题答案.docx

数值分析上机题答案

数值分析上机题

姓名:

武均学号:

142648

习题1

17.(上机题)舍入误差与有效数

,其精确值为

(1)编制按从大到小的顺序

,计算

的通用程序。

(2)编制按从小到大的顺序

,计算

的通用程序。

(3)按两种顺序分别计算

,并指出有效位数。

(编制程序时用单精度)

(4)通过本上机题你明白了什么?

按从大到小的顺序计算

的通用程序为:

#include

floatsum(floatN)

{

floatj,s,sum=0;

for(j=2;j<=N;j++)

{

s=1/(j*j-1);

sum+=s;

}

returnsum;

}

按从小到大的顺序计算

的通用程序为:

#include

floatsum(floatN)

{

floatj,s,sum=0;

for(j=N;j>=2;j--)

{

s=1/(j*j-1);

sum+=s;

}

returnsum;

}

从大到小的顺序的值

从小到大的顺序的值

精确值

有效位数

从大到小

从小到大

0.740049

0.74005

0.740049

6

5

0.749852

0.7499

0.7499

4

4

0.749852

0.749999

0.749999

3

6

通过本上机题,看出按两种不同的顺序计算的结果是不相同的,按从大到小的顺序计算的值与精确值有较大的误差,而按从小到大的顺序计算的值与精确值吻合。

从大到小的顺序计算得到的结果的有效位数少。

计算机在进行数值计算时会出现“大数吃小数”的现象,导致计算结果的精度有所降低,我们在计算机中进行同号数的加法时,采用绝对值较小者先加的算法,其结果的相对误差较小。

习题2

20.(上机题)Newton迭代法

(1)给定初值

及容许误差

,编制Newton法解方程

根的通用程序。

(2)给定方程

,易知其有三个根

1.由Newton方法的局部收敛性可知存在

,当

时,Newton迭代序列收敛于根

试确定尽可能大的

2.试取若干初始值,观察当

时Newton序列是否收敛以及收敛于哪一个根。

(3)通过本上机题,你明白了什么?

解:

(1)编制的通用程序:

#include

#include

#defineeps0.000001/给定容许误差

floatf(floatx)//定义函数f(x)

{

floatf;

f=x*x*x/3-x;//f(x)的表达式;

return(f);

}

floatdf(floatx)//定义函数df(x),计算f(x)的导函数

{

floatdf;

df=x*x-1;//f(x)导函数的表达式;

return(df);

}

voidmain(void)

{

floatx0,x1,a;

intk=0;

cout<<"请输入初值x0:

";

cin>>x0;

do

{

a=-f(x0)/df(x0);

x1=x0+a;

k++;

x0=x1;

}

while(fabs(a)>eps);

cout<

//输出迭代的次数和根值

}

(2)计算迭代序列收敛于根

的尽可能大的

的函数为:

#include

#include

voiddelay(intn)//定义延时函数

{for(n=10000;n>0;n--);}

#defineeps0.000001

floatf(floatx)//定义函数f(x)

{

floatf;

f=x*x*x/3-x;//f(x)的表达式;

return(f);

}

floatdf(floatx)//定义函数df(x),计算f(x)的导函数

{

floatdf;

df=x*x-1;//f(x)导函数的表达式;

return(df);

}

intjudgement(floatz)

{

intcount=5;

floatx0,x1,type,type1;

x0=z;

while(count-->0)

{

x1=x0-f(x0)/df(x0);

type=fabs(x1);

type1=fabs(x1-x0);//调试值用

cout<<"count="<

if(fabs(x1-x0)

return1;

x0=x1;

delay(30000);//调试值用

}

return0;

}

voidmain(void)

{

floatdelta=0;

intflag=1;

while(flag==1)

{

cout<<"方程的根为:

"<<'\n';

delta+=eps;

flag=judgement(delta);

}

cout<<"输出方程根收敛的区间值:

\n";

cout<

}

当步长为0.001时,程序计算出的δ的为δ=0.774,即在区间(-0.774,0.774)内迭代序列收敛于0。

对于不同得初始值收敛于不同的根,

在(-∞,-1)内收敛于

,在(-0.774,0.774)内收敛于

,在(1,+∞)内收敛于

,但在内(0.774,1)和(-1,0.774)均可能收敛于

分别为方程的精确解。

分析:

对于不同的初值,迭代序列会收敛于不同的根,所以在某个区间内求根对于初值的选取有很大的关系。

产生上述结果的原因是区间不满足大范围收敛的条件。

 

习题3

39.(上机题)列主元Gauss消去法

对于某电路的分析,归结为求解线性方程组RI=V。

其中,

31-13000-10000

-1335-90-110000

0-931-1000000

00-1079-30000-9

000-3057-70-50

0000-747-3000

00000-304100

0000-50027-2

000-9000-229

 

 

R=

 

VT=(-15,27,-23,0,-20,12,-7,7,10)T

(1)编制解n阶线性方程组Ax=b的列主元三角分解法的通用程序;

(2)用所编制的程序解线性方程组RI=V,并打印出解向量,保留五位有效数;

(3)本编程之中,你提高了哪些编程能力?

程序为:

#include

#include

voidmain(void)

{

inti,j,n,k,q;

floata[10][11],s[10],s1[10];

cout<<"请输入n的值:

";

cin>>n;

cout<<"输入数组a:

"<

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

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

cin>>a[i][j];//给矩阵a赋值

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

{

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

cout<

cout<<'\n';

}//输出数组a

cout<<"'''''''''''''''''''''''''"<<'\n';

//进行第一行和第一列元素的求取'''''''''''''''''''''''''//

intt=1;

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

{s[i]=a[i][1];}

floatmax=fabs(s[1]);

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

if(fabs(s[i])>max)

{

max=fabs(s[i]);

t=i;

}

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

{

floatb=a[1][j];

a[1][j]=a[t][j];

a[t][j]=b;

}//进行第一列主元互换

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

a[i][1]=a[i][1]/max;//第一列除以a[1][1]

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

{

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

cout<

cout<<'\n';

}

//输出进行第一步变换的数组a

cout<<"'''''''''''''''''''''''''"<<'\n';

//进行第k步分解'''''''''''''''''''''''''''''''''''''''''//

for(k=2;k<=n;k++)

{

for(i=k;i<=n;i++)

{

floatsum=0;

for(q=1;q

sum+=a[i][q]*a[q][k];

s1[i]=a[i][k]-sum;

}

intl=k;

floatm=fabs(s1[k]);

for(i=k;i<=n;i++)

//比较第k步分解的第k列值的大小

{

if(fabs(s1[i])>m)

{

m=fabs(s1[i]);

l=i;//返回行值

}

}

for(j=1;j<=n+1;j++)//交换两行元素

{

floats2=a[k][j];

a[k][j]=a[l][j];

a[l][j]=s2;

}

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

//算出第k行行元素的值

{

floatsum1=0;

for(q=1;q

sum1+=a[k][q]*a[q][j];

a[k][j]=a[k][j]-sum1;

}

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

//算出第k列列元素的值

{

floatsum2=0;

for(q=1;q

sum2+=a[i][q]*a[q][k];

a[i][k]=(a[i][k]-sum2)/(a[k][k]);

}

}//第k步分解结束

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

{

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

cout<

cout<<'\n';

}//输出改变后的数组

//输出解'''''''''''''''''''''''''''''''''''''''''''''''''''''''//

floatx[10];

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

{

x[n]=a[n][n+1]/a[n][n];

floatsum3=0;

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

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

x[i]=(a[i][n+1]-sum3)/a[i][i];

}//回代过程

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

{

cout<<'x'<

}//输出解向量

}

结果:

方程的解为:

x1=-0.28923,x2=0.34544,x3=-0.71281,

x4=-0.22061,x5=-0.43040,x6=0.15431,

x7=-0.057823,x8=0.20105,x9=0.29023。

分析:

我感觉是提高了查错误点的能力和编循环语句的能力,即利用很规整的迭代公式进行编程。

另外列主元三角分解法的阶梯步骤有了更深的了解!

40.逐次超松弛迭代法

(1)编制解n阶线性方程组Ax=b的SOR方法的通用程序(要求

);

(2)对于39题中所给的线性方程组,取松弛因子

,容许误差

,打印松弛因子、迭代次数、最佳松弛因子及解向量。

程序为:

#include

#include

#defineeps0.5e-5//迭代误差

voidmain(void)

{

inti,j,l;

floatw,t;

floatm[9];

floatsum;

floata[9][9]={{31,-13,0,0,0,-10,0,0,0},{-13,35,-9,0,-11,0,0,0,0},{0,-9,31,-10,0,0,0,0,0},{0,0,-10,79,-30,0,0,0,-9},{0,0,0,-30,57,-7,0,-5,0},{0,0,0,0,-7,47,-30,0,0},{0,0,0,0,0,-30,41,0,0},{0,0,0,0,-5,0,0,27,-2},

{0,0,0,-9,0,0,0,-2,29}};

floatb[9]={-15,27,-23,0,-20,12,-7,7,10};

floatmax(floatm[9]);

for(t=1;t<=99;t++)

{

l=0;

floatx0[9]={1,1,1,1,1,1,1,1,1};

floatx1[9]={1,1,1,1,1,1,1,1,1};

w=t/50;

do

{

for(i=0;i<9;i++)

{x0[i]=x1[i];}

for(i=0;i<9;i++)

{

sum=0;

for(j=0;j

{

sum=sum+a[i][j]*x1[j];

}

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

{sum=sum+a[i][j]*x0[j];}

x1[i]=(1-w)*x0[i]+w*(b[i]-sum)/a[i][i];}//解出九个解

for(i=0;i<9;i++)

{

m[i]=x1[i]-x0[i];}

l++;

}while(max(m)>=eps);

if(max(m)<=eps)

{cout<<"迭代次数="<

for(i=0;i<9;i++)

cout<<"x1"<<"["<

cout<<"-------------------------------------"<<'\n';}

}

}

floatmax(floatm[9])//求出最大的迭代误差

{

floatk;

k=(fabs(m[0]));

for(inti=1;i<9;i++)

{

if(fabs(m[i])>k)

k=fabs(m[i]);

}

returnk;

}

结果为:

ω迭代次数ω迭代次数ω迭代次数ω迭代次数

0.021291

0.04700

0.06486

0.08373

0.10303

0.12255

0.14221

0.16194

0.18173

0.20156

0.22142

0.24130

0.26120

0.28111

0.30103

0.3296

0.3490

0.3685

0.3880

0.4075

0.4271

0.4468

0.4664

0.4861

0.5058

0.5255

0.5453

0.5651

0.5848

0.6046

0.6244

0.6442

0.6641

0.6839

0.7037

0.7236

0.7434

0.7633

0.7832

0.8030

0.8229

0.8428

0.8627

0.8826

0.9025

0.9224

0.9423

0.9622

0.9821

1.0020

1.0219

1.0418

1.0617

1.0816

1.1015

1.1215

1.1414

1.1612

1.1810

1.2011

1.2212

1.2412

1.2613

1.2813

1.3014

1.3215

1.3415

1.3616

1.3817

1.4018

1.4219

1.4419

1.4620

1.4821

1.5022

1.5224

1.5425

1.5627

1.5830

1.6031

1.6234

1.6436

1.6639

1.6844

1.7049

1.7255

1.7460

1.7671

1.7881

1.8097

1.82121

1.84157

1.86228

1.88398

1.901582

1.925427

1.942178

1.961374

1.981009

从1.92到2.00均出现不合理的迭代次数,迭代次数偏大。

不是合理的迭代值。

当初值为x=(1,1,1,1,1,1,1,1,1,)T时,从上表可以看出,最佳松弛因子为ω=1.18,迭代次数仅为10次,方程的解为:

x1=-0.289231,x2=0.345437,x3=-0.712811,

x4=-0.220608,x5=-0.430400,x6=0.154309,

x7=-0.057823,x8=0.201054,x9=0.290229。

 

习题4

37.(上机题)3次样条插值函数

(1)编制求第一型3次样条插值函数的通用程序;

(2)已知汽车曲线型值点的数据如下:

0

1

2

3

4

5

6

7

8

9

10

2.51

3.30

4.04

4.70

5.22

5.54

5.78

5.40

5.57

5.70

5.80

端点条件为

=0.8,

=0.2。

用所编制程序求车门的3次样条插值函数S(x),并打印出S(i+0.5)(i=0,1,…9)。

解:

通用程序:

#include

voidmain(void)

{

floatx[11];//存放数组x[j]

floaty[11];//存放数组y[j]

floath[11];//存放数组h[j]

floatu[11];//存放数组u[j]

floatv[11];//存放数组v[j]

floatd[11];//存放数组d[j]

floatM[11];//存放数组M[j]

floatb[11];//存放数组b[j]

floatt[11],l[11],yy[11],s[4],aa1,aa2,aa3,aa4;

floats1[10];

inti,j,n;

floatxx;//x为区间值

//将初值初始化

cout<<"请输入n的值:

\n";

cin>>n;

cout<<"输入数组x:

\n";

for(i=0;i<=n;i++)cin>>x[i];

cout<<"输入数组y:

\n";

for(i=0;i<=n;i++)cin>>y[i];

//输入端点值

floatdf[2];

cout<<"输入两个端点值:

\n";

for(i=0;i<2;i++)cin>>df[i];

//利用书本上的算法求出所需要的值

//求出h[j]的值

for(j=0;j<=n-1;j++)

{

h[j]=x[j+1]-x[j];

cout<<'h'<<'['<

}

cout<

//求出u[j]和v[j]的初值

v[0]=1;

u[n]=1;

for(j=1;j<=n-1;j++)

{

u[j]=h[j-1]/(h[j-1]+h[j]);

v[j]=h[j]/(h[j-1]+h[j]);

}

//求出d[j]的值

for(j=1;j

{d[j]=6*((y[j+1]-y[j])/h[j]-(y[j]-y[j-1])/h[j-1])/(h[j]+h[j-1]);}

d[0]=6*((y[1]-y[0])/h[0]-df[0])/h[0];

d[n]=6*(df[1]-(y[n]-y[n-1])/h[n-1])/h[n-1];

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

{

cout<<'u'<<'['<

}

cout<

for(j=0;j

{

cout<<'v'<<'['<

}

cout<

for(j=0;j<=n;j++)

{

cout<<'d'<<'['<

}

cout<

//利用书本上的追赶法求解方程组

for(i=0;i<=n;i++)

{b[i]=2;}

cout<

t[0]=b[0];

yy[0]=d[0];

//消元过程

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

{

l[i]=u[i]/t[i-1];

t[i]=b[i]-l[i]*v[i-1];

yy[i]=d[i]-l[i]*yy[i-1];

}

//回代过程

M[n]=yy[n]/t[n];

for(i=n-1;i>=0;i--)

{

M[i]=(yy[i]-v[i]*M[i+1])/t[i];

}

//将M[j]的值输出

for(i=0;i<=n;i++)

{cout<<'M'<<'['<

//输出插值多项式的系数

for(j=0;j

{

s[0]=y[j];

s[1]=(y[j+1]-y[j])/h[j]-(M[j]/3+M[j+1]/6)*h[j];

s[2]=M[j]/2;

s[3]=(M[j+1]-M[j])/(6*h[j]);

cout<<"当x的值在区间"<<'x'<<'['<

\n";

for(intk=0;k<4;k++)

{

cout<<'s'<<'['<

}

cout<

}

}

(2)编制的程序求车门的3次样条插值函数S(x):

x属于区间[0,1]时;S(x)=2.51+0.8(x)-0.00

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

当前位置:首页 > 求职职场 > 简历

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

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