东南大学计算方法与实习实验报告
学院:电子科学与工程学院
学号:06A*****
姓名:***
指导老师:***
实习题1
4、设S N=Σ
(1)编制按从大到小的顺序计算S N的程序;
(2)编制按从小到大的顺序计算S N的程序;
(3)按两种顺序分别计算S1000,S10000,S30000,并指出有效位数。
解析:从大到小时,将S N分解成S N-1=S N-,在计算时根据想要得到的值取合适的最大的值作为首项;同理从小到大时,将S N=S N-1+ ,则取S2=1/3。
则所得式子即为该算法的通项公式。
(1)从大到小算法的C++程序如下:
/*从大到小的算法*/
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
const int max=34000; //根据第(3)问的问题,我选择了最大数为34000作为初值
void main(){
int num;
char jus;
double cor,sub;
A: cout<<"请输入你想计算的值"<<'\t';
cin>>num;
double smax=1.0/2.0*(3.0/2.0-1.0/max-1.0/(max+1)),temps;
double S[max];
// cout<<"s["<<max<<"]="<<setprecision(20)<<smax<<'\n';
for(int n=max;n>num;){
temps=smax;
S[n]=temps;
n--;
smax=smax-1.0/((n+1)*(n+1)-1.0);
}
cor=1.0/2.0*(3.0/2.0-1.0/num-1.0/(num+1.0)); //利用已知精确值公式计算精确值sub=fabs(cor-smax); //double型取误差的绝对值
cout<<"用递推公式算出来的s["<<n<<"]="<<setprecision(20)<<smax<<'\n';
cout<<"实际精确值为"<<setprecision(20)<<cor<<'\n';
cout<<"则误差为"<<setprecision(20)<<sub<<'\n';
cout<<"是否继续计算S[N],是请输入Y,否则输入N!"<<endl;
cin>>jus;
if ((int)jus==89||(int)jus==121) goto A;
}
(2)从小到大算法的C++程序如下:
/*从小到大的算法*/
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
void main(){
int max;
A: cout<<"请输入你想计算的数,注意不要小于2"<<'\t';
cin>>max;
double s2=1.0/3.0,temps,cor,sub;
char jus;
double S[100000];
for(int j=2;j<max;){
temps=s2;
S[j]=temps;
j++;
s2+=1.0/(j*j-1.0);
}
cor=1.0/2.0*(3.0/2.0-1.0/j-1.0/(j+1.0)); //利用已知精确值公式计算精确值sub=fabs(cor-s2); //double型取误差的绝对值
cout<<"用递推公式算出来的s["<<j<<"]="<<setprecision(20)<<s2<<'\n';
cout<<"实际精确值为"<<setprecision(20)<<cor<<'\n';
cout<<"则误差为"<<setprecision(20)<<sub<<'\n';
cout<<"是否继续计算S[N],是请输入Y,否则输入N!"<<endl;
cin>>jus;
if ((int)jus==89||(int)jus==121) goto A;
}
(3)
(注:因为程序中setprecision(20)表示输出数值小数位数20,则程序运行时所得到的有效数字在17位左右)
ii.选择从小到大的顺序计算S1000、S10000、S30000的值
需要计算的项S1000S10000S30000
计算值0.74900049950049996 0.74966672220370571 0.74996666722220728
实际精确值0.74900049950049952 0.74990000499950005 0.74996666722220373
误差 4.4408920985006262*10-16 5.6621374255882984*10-15 3.5527136788005009*10-15有效数字17 17 17
附上部分程序运行图:
iii.实验分析
通过C++程序进行计算验证采用从大到小或者从小到大的递推公式算法得到的数值基本稳定
且误差不大。
而相比之下,从大到小比从小到大的误差更加小,则证明从大到小的算法更加
好。
需要说明的是C++程序所计算的结果事实上也同实际数值有些许误差。
在实验过程中发现
S2=1/3化成小数应该为0.3关于3的无限循环,而利用C++程序计算的结果为
0.33333333333333337,说明了其与实际数值依然存在有误差。
但是毕竟利用递推公式和计
算所给的精确值公式时都将计算机的误差计算进去了,所以理论上可以忽略这部分误差。
值得一提的是上文从大到小的算法程序中,我采取了34000作为最大值的初始值,而不是用
其他相对于比较容易取的特殊的值,譬如30000,50000,甚至于100000。
事实上在选取该
值的时候比较犹豫,于是采取了试值的方法,结果发现50000以后程序会跑飞,于是50000
以上的值便舍去。
在试比较大的例如从30000以上开始选取的时候,发现从30000开始增大
会使得计算出来的S2的值与1/3的理论计算值误差越来越小,到34000时达到最小,为
0.33333333333333304,,而到35000该值的误差又开始增大。
所以选取34000比较令我满意。