- 题目:
运行最大公约数的常用算法,并进行程序的调式与测试,要求程序设计风格良好,并添加异常处理模块(如输入非法等)。
- 题目分析:
本道题主要是想让大家了解四个求最大公约数的常用算法并计算他们的时间复杂度,对算法的书写要求不高,主要是运用和调试。
- 算法构造:
1 辗转相除法
2 穷举法
3 更减相损法
4 stein法
- 算法实现:
#include<iostream.h>
#include<math.h>
#include<cstdlib>
#include<ctime>
#include<windows.h>
#include<stdio.h>
int M1 (int a,int b) /*辗转相除法函数求两数的最大公约数*/
{
int temp; /*定义整型变量*/
if(a<b) /*通过比较求出两个数中的最大值和最小值*/
{ temp=a;a=b;b=temp;} /*设置中间变量进行两数交换*/
while(b!=0) /*通过循环求两数的余数,直到余数为0*/
{
temp=a%b;
a=b; /*变量数值交换*/
b=temp;
}
return (a); /*返回最大公约数到调用函数处*/
}
int M2 (int a,int b) /*穷举法函数求两数的最大公约数*/
{
int temp; /*定义义整型变量*/
temp=(a>b)?b:a; /*采种条件运算表达式求出两个数中的最小值*/
while(temp>0)
{
if (a%temp==0&&b%temp==0) /*只要找到一个数能同时被a,b所整除,则中止循环*/
break;
temp--; /*如不满足if条件则变量自减,直到能被a,b所整除*/
}
return (temp); /*返回满足条件的数到主调函数处*/
}
int M3(int m,int n)/*更减相损法求最大公约数*/
{
int i=0,temp,x;
while(m%2==0 && n%2==0) //判断m和n能被多少个2整除
{
m/=2;
n/=2;
i+=1;
}
if(m<n) //m保存大的值
{
temp=m;
m=n;
n=temp;
}
while(x)
{
x=m-n;
m=(n>x)?n:x;
n=(n<x)?n:x;
if(n==(m-n))
break;
}
if(i==0)
return n;
else
return (int )pow(2,i)*n;
}
int M4(int u,int v)/*stein法*/
{
if (u == 0) return v;
if (v == 0) return u;
// look for factors of 2
if (~u & 1) // u is even
{
if (v & 1) // v is odd
return M4(u >> 1, v);
else // both u and v are even
return M4(u >> 1, v >> 1) << 1;
}
if (~v & 1) // u is odd, v is even
return M4(u, v >> 1);
// reduce larger argument
if (u > v)
return M4((u - v) >> 1, v);
return M4((v - u) >> 1, u);
}
int main()
{
int i,a[10000],c,d,e,f;
srand(int(time(0)));
for(i=0;i<10000;i++)/*生成随机数并给a[i]赋值*/
a[i]=rand();
cout<<endl;
clock_t start1 = clock();
for(i=0;i<9999;i++)/*调用M1函数*/
{
c=M1(a[i],a[i+1]);
cout<<c<<endl;
} clock_t finish1 = clock();
double consumeTime = (double)(finish1-start1)/CLOCKS_PER_SEC;//注意转换为double的位置
//cout<<"运行时间为:"<<seconds<<endl;
cout<<endl;
clock_t start2 = clock();
for(i=0;i<9999;i++)/*调用M2函数*/
{
d=M2(a[i],a[i+1]);
cout<<d<<endl;
}
clock_t finish2 = clock();
double consumeTime2 = (double)(finish2-start2)/CLOCKS_PER_SEC;//注意转换为double的位置
printf("%f ",consumeTime2);
cout<<endl;
clock_t start3 = clock();
for(i=0;i<9999;i++)/*调用M3函数*/
{
e=M3(a[i],a[i+1]);
cout<<e<<endl;
}
clock_t finish3 = clock();
double consumeTime3= (double)(finish3-start3)/CLOCKS_PER_SEC;//注意转换为double的位置
cout<<endl;
clock_t start4 = clock();
for(i=0;i<9999;i++)/*调用M4函数*/
{
f=M4(a[i],a[i+1]);
cout<<f<<endl;
}
clock_t finish4= clock();
double consumeTime4= (double)(finish4-start4)/CLOCKS_PER_SEC;//注意转换为double的位置
printf("%f ",consumeTime);
printf("%f ",consumeTime2);
printf("%f ",consumeTime3);
printf("%f ",consumeTime4);
cout<<endl;
return 0;
}
- 测试:
随机产生100个随机数,测试好几次并不能准确比较算法时间性能。
之后又增加到1000个,还是不太能准确计算。
10000个的时候,可以准确得出第四种算法速度最快
- 调试:
产生随机数的调试和时间调试。
- 经验归纳:
一开始我理解的比较简单,以为就是输入几个数据比一比,后来发现小数据并不能准确得出结果,所以我利用随机数组产生较多的随机数,再比较时间,其实一开始也遇到很多问题,比如说产生随机数的不确定性导致四个算法比较不均匀,测试不准确,一开始用rand()函数产生伪随机数其实并不是随机的,后来我加入时间函数,以每次电脑时间的不同调整开始的数字,这样就能产生真正的随机数。由于输出没改,一直输出的是整形,导致时间是0秒,后来改为浮点型才能准确输出时间,这次上机作业我学会了如何调用time类的时间函数,会利用rand()函数生成多个随机数,对程序的理解也更加深入了,懂得遇到困难在网上寻找解决办法更加方便,独立性感觉有所提高。