东南大学数值分析上机题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++)