1.题目分析
①首先写出求最大公约数算法,用了四种方法,分别是,辗转相除法,穷举法,更相减损法,Stein算法,这四种方法通过不同的逻辑思维求出最大最大公约数,运行时间也各不相同。
②其次在进行编程时,要考虑到异常处理,求随机数的异常处理:超过数组范围,手动输入的异常处理:输入负数为不合法。
③还有就是用C语言中生产随机数及计算运行时间,并生成指定范围内指定个数的随机数。
④将获取的随机数运用在计算最大公约数的函数当中,最后用二维数组存放随机数,以把随机数以数组形式作为实参传入函数中。
2.算法构造
绘制出所有算法的流程图以及N-S盒图。

3.算法实现
程序源代码(请写入必要的注释)。
#include"stdio.h"
#include<math.h>
#include<stdlib.h>
#include<time.h>
int divisor1(int a,int b);
int divisor2(int a,int b);
int gcd(int m,int n);
int Stein(unsigned int x,unsigned int y);
void main()
{
clock_t start,finish;//开始结束两个时间
srand(10);
double time;//定义运行时间
int k,t1;
int i,j,p;
int min,max,n;
int a[100][2];
printf("你想随机产生多少组数:\n");
scanf("%d",&n);
if(n>100)
{printf("超过数组范围,请重新输入:");
scanf("%d",&n);
}
printf("请依次输入随机数取值的最小值,最大值(之后将在这个范围内产生随机数)\n");
scanf("%d%d",&min,&max);
// srand((unsigned)time(NULL));
start=clock();//获取开始时间
for(i=0;i<n;i++)//获取随机数并进行输出
{
for(j=0;j<2;j++)
{
a[i][j]=rand()%100;//将随机数赋给二维数组
printf("%d ",a[i][j]);
}
}
/*手动输入*/
/*printf("输入两个数:");
scanf("%d%d",&m,&n);
for(;m<0||n<0;)
{
printf("输入数不合法,请重新输入:\n");
scanf("%d%d",&m,&n1);
}*/
printf("\n方法1:辗转相除法;\n方法2:穷举法;\n方法3:更相减损法;\n方法4:Stein算法\n请选择:\n");
scanf("%d",&k);//选择使用方法
printf("最大公约数为:\n");
for(p=0;p<n;p++)
{
switch(k)
{
case 1: {t1=divisor1(a[p][0],a[p][1]);//调用计算最大公约数的函数
break;}
case 2:{t1=divisor2(a[p][0],a[p][1]);
break;}
case 3:{t1=gcd(a[p][0],a[p][1]);
break;}
case 4:{t1=Stein(a[p][0],a[p][1]);
break;}
}
printf("%d ",t1);
}
finish=clock();//获取结束时间
printf("\n");
time=(double)(finish-start)/CLOCKS_PER_SEC;
printf("RunningTime:\n%f 毫秒\n",time);//显示运行时间
}
int divisor1(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 divisor2(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--;
}
return(temp);
}
int gcd(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 Stein(unsigned int x,unsigned int y)
{
int factor=0;
int temp;
if(x<y)
{
temp=x;
x=y;
y=temp;
}
if(0==y)
{
return 0;
}
while(x!=y)
{
if(x&0x1)
{
if(y&0x1)
{
y=(x-y)>>1;
x-=y;
}
else
{
y>>=1;
}
}
else
{
if(y&0x1)
{
x>>=1;
if(x<y)
{
temp=x;
x=y;
y=temp;
}
}
else
{
x>>=1;
y>>=1;
++factor;
}
}
}
return (x<<factor);
}
4.调试、测试及运行结果(至少比较4种GCD算法在给定不同规模测试数据的情况下的平均运行时间)
5、经验归纳
在本次上机中,我学到了输入两个数,求其最大公约数的算法,在其之上,做出改动,学习了如何在C语言中生产随机数及计算运行时间,并生成指定范围内指定个数的随机数,在time.h头文件下,先获取开始时间和结束时间start=clock(),finish=clock();最后计算运行时间time=(double)(finish-start)/CLOCKS_PER_SEC;
在比较4种不同算法在给定不同规模测试数据的情况下的平均运行时间后,得出辗转相除法所用时间最少,更相减损法用时最大;在编程中遇到的问题是,如何将获取的随机数运用在计算最大公约数的函数当中,最后我用了二维数组存放随机数,以把随机数以数组形式作为实参传入函数中。