数值分析上机作业最强版
- 格式:docx
- 大小:338.68 KB
- 文档页数:25
数值分析上机作业
**:**
学号:******
专业:道路与铁道工程
院系:交通学院
****:***
日期:2015年1月
习题一
1 题目
17.(上机题)舍入误差与有效数 设2
21
1N
N j S j ==-∑
,其精确值为1311221N N ⎛⎫
-- ⎪+⎝⎭
。 (1)编制按从大到小的顺序22
2
11
1
2131
1
N S N =+++
---,计算N S 的通用程序; (2)编制按从小到大的顺序22211
11(1)1
21
N S N N =
+++
----,计算N S 的通用程序; (3)按两种顺序分别计算210S ,410S ,610S ,并指出有效位数。(编制程序时用单精度);
(4)通过本上机题你明白了什么?
2 通用程序代码
2.1 按从小到大的顺序计算N S
void AscendSum(unsigned long int N)// 计算从大到小的总和 {
for (unsigned long int j=2;j<=N;j++) ascendSum+=(float )1.0/(j*j-1);
cout<<"Sum From 1 to N (Ascend) is: "< } 2.2 按从大到小的顺序计算N S void DescendSum(unsigned long int N)//计算从小到大的总和 { for (unsigned long int j=N;j>=2;j--) descendSum+=(float )1.0/(j*j-1); cout<<"Sum From N to 1 (Descend) is: "< } 3计算结果展示 图1 N=100时的计算结果 图2 N=10000时的计算结果 图3 N=1000000时的计算结果 表1-1 计算结果汇总 N S 精确值 按从小到大 按从大到小 N S 值 有效位数 N S 值 有效位数 210S 0.7400494814 0.7400494814 10 0.740049541 6 410S 0.7498999834 0.7498521209 4 0.7498999834 10 610S 0.7499989867 0.751856029 2 0.7529925108 2 4 计算结果分析 (1)如果采用单精度数据结构进行计算,则相较于双精度的数据结果,由于数据存储字长的限制导致计算机存在较大的舍入误差,因此本程序采用的是双精度数据存储方式。 (2)由计算结果可知,正序计算和逆序计算的精度是不稳定的。由计算结果可以发现,当N=100时,正序计算(1-N )的精度较高;当N=10000时,逆序计算(N-1)的精度较高;当N=1000000时,正序计算和逆序计算的精度一样。 当然,和其他同学做出来的结果对比,结论并不一致。我个人分析这是因为电脑的硬件、软件(位数)不同等原因导致的。但总体而言,在N 较小时,正序计算精度高于逆序计算的精度。当N 较大时,正序和逆序计算的精度接近。 (3)由于计算机的实际计算过程是一种舍入机制,故对于我们计算所采用的加法交换律是不成立的。计算机中若干数相加时,先要进行对阶操作,即将两数的阶数统一为绝对值较大的数的阶数。这样一来将导致绝对值较小的数的有效数字可能会大量损失,增大舍入误差,即所谓的“大数吃小数”现象。为了避免这种现象的出现,在进行加减法的时候应该先将绝对值较小的数相加,再与绝对值较大的数相加这样按阶逐步递增的相加。 5 完整代码 #include float accurateSum=0,ascendSum=0,descendSum=0; void Delimiter()//输出一系列星号以间隔 { for (int i=1;i<=50;i++) cout<<"*"; cout< } void Error(float Sum)//计算绝对误差 { float error; error=fabs(Sum-accurateSum); int flag; for(flag=0;flag<10;flag++) { error=error*10; if (error>0.5) break; } cout<<"There are "< } void AccurateSum(unsigned long int N)//计算精确值 { accurateSum=0.5*(1.5-(float)1/N-(float)1/(N+1)); cout<<"Accurate sum is: "< Delimiter(); } void AscendSum(unsigned long int N)//计算从大到小的总和 { for(unsigned long int j=2;j<=N;j++) ascendSum+=(float)1.0/(j*j-1); cout<<"Sum From 1 to N (Ascend) is: "< Error(ascendSum); Delimiter(); } void DescendSum(unsigned long int N)//计算从小到大的总和 { for(unsigned long int j=N;j>=2;j--) descendSum+=(float)1.0/(j*j-1); cout<<"Sum From N to 1 (Descend) is: "< Error(descendSum); Delimiter(); } void main()//主程序 {