东南大学数值分析上机题C参考答案

  • 格式:doc
  • 大小:236.50 KB
  • 文档页数:16

文档从互联网中收集,已重新修正排版,word格式支持编辑,如有帮助欢迎下载支持。

1word格式支持编辑,如有帮助欢迎下载支持。 数值分析上机题

姓名:陈作添 学号:040816

习题1

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

设2211NNjSj,其精确值为1311221NN。

(1)编制按从大到小的顺序22211121311NSN,计算NS的通用程序。

(2)编制按从小到大的顺序2221111(1)121NSNN,计算NS的通用程序。

(3)按两种顺序分别计算210S,410S,610S,并指出有效位数。(编制程序时用单精度)

(4)通过本上机题,你明白了什么?按从大到小的顺序计算NS的通用程序为:

#include

float sum(float N)

{

float j,s,sum=0;

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

{

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

sum+=s;

}

return sum;

} 按从小到大的顺序计算NS的通用程序为:

#include

float sum(float N)

{

float j,s,sum=0;

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

{

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

sum+=s;

}

return sum;

} 从大到小的顺序的值 从小到大的顺序的值 精确值 有效位数

从大到小 从小到大

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 习题2

20.(上机题)Newton迭代法

(1)给定初值0x及容许误差,编制Newton法解方程()0fx根的通用程序。

(2)给定方程3()/30fxxx,易知其有三个根13x,20x,33x。

1.由Newton方法的局部收敛性可知存在0,当0(,)x时,Newton迭代序列收敛于根2x。试确定尽可能大的。

2.试取若干初始值,观察当0(,1)x,(1,),(,),(,1),(1,)时Newton序列是否收敛以及收敛于哪一个根。

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

解:(1)编制的通用程序:#include

#include

#define eps 0.000001 /给定容许误差

float f(float x) //定义函数f(x)

{

float f;

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

return(f);

}

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

{

float df;

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

return (df);

}

void main(void) {

float x0,x1,a;

int k=0;

cout<<"请输入初值x0:";

cin>>x0;

do

{

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

x1=x0+a;

k++;

x0=x1;

}

while(fabs(a)>eps);

cout<

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

}(2)计算迭代序列收敛于根2x的尽可能大的的函数为:#include

#include

void delay(int n) //定义延时函数

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

#define eps 0.000001

float f(float x) //定义函数f(x)

{

float f;

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

}

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

{

float df;

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

return (df); }

3 int judgement(float z)

{

int count=5;

float x0,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)

return 1;

x0=x1;

delay(30000); //调试值用

} return 0;

}

void main(void)

{

float delta=0;

int flag=1;

while(flag==1)

{

cout<<"方程的根为:"<<'\n';

delta+=eps;

flag=judgement(delta);

}

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

cout<

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

对于不同得初始值收敛于不同的根, 0x在(-∞,-1)内收敛于*1x,在(-0.774,0.774)内收敛于2x,在(1,+∞)内收敛于3x,但在内(0.774,1)和(-1,0.774)均可能收敛于*1x和3x。*1x,2x,3x分别为方程的精确解。

分析:对于不同的初值,迭代序列会收敛于不同的根,所以在某个区间内求根对于初值的选取有很大的关系。产生上述结果的原因是区间不满足大范围收敛的条件。

习题3

35.(上机题)列主元三角分解法对于某电路的分析,归结为求解线性方程组RI=V。

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

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

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

程序为:#include

#include

void main(void)

{

int i,j,n,k,q;

float a[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';

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

4 '''''''''''''''''''''''''//

int t=1;

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

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

float max=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++)

{

float b=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++)

{

float sum=0;

for(q=1;q

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

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

}

int l=k;

float m=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++) //交换两行元素

{

float s2=a[k][j];

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

a[l][j]=s2;

}

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

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

{

float sum1=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列列元素的值

{

float sum2=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';

} //输出改变后的数组

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

float x[10];

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

{

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

float sum3=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++)