题目:求解最大公约数
算法实现:
(1)辗转相除法:
步骤一:若a%b为0,则b就是a,b的最大公约数;
步骤一:a%b不为0,将b赋值给a,a%b赋值g给b,重复步骤一
(2)穷举法:
求出a,b中较小的值min,让min值逐渐减小到一,过程中如果a,b%min都为0,则此时的min就是最大公约数
(3)更相减损法:
第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数
(4)stein法:
对两个正整数 x>y :
1.均为偶数 gcd( x,y ) =2gcd( x/2,y/2 );
2.均为奇数 gcd( x,y ) = gcd( (x+y)/2,(x-y)/2 );
2.x奇y偶 gcd( x,y ) = gcd( x,y/2 );
3.x偶y奇 gcd( x,y ) = gcd( x/2,y ) 或 gcd( x,y )=gcd( y,x/2 );
当x==y时,递归结束。
C语言实现
#include<stdio.h>
#include<time.h>
#include<math.h>
// 辗转相除法求最大公约数——循环实现
int divsion1(int a, int b){
// 检查数据输入合法性
if (a < 1 || b < 1){
return -1;
}
int c;
while (c = a % b){
a = b;
b = c;
}
return b;
}
// 辗转相除法求最大公约数——递归实现
int divsion2(int a, int b){
// 检查数据输入合法性
if (a < 1 || b < 1){
return -1;
}
if (a % b){
return divsion2(b, a%b);
}
return b;
}
// 枚举法求最大公约数
int enumComputing(int a, int b){
int min = a < b ? a : b;
for (; min > 1 && (a % min || b % min); min--);
return min;
}
// 枚举法求最大公约数
int enumMinMultiple(int a, int b){
int max = a > b ? a : b;
int min = a < b ? a : b;
int t = max;
while (max % min){
max += t;
}
return max;
}
// 更像减损法求最大公约数
int getMinMultiple(int a, int b){
int n = 0;
while (a % 2 == 0 && b % 2 == 0){
a /= 2;
b /= 2;
n++;
}
if (a < b){
int t = a;
a = b;
b = t;
}
int x = a - b;
while (x){
a = b > x ? b : x;
b = b < x ? b : x;
if (a - b == b){
break;
}
x = a - b;
}
if (! n){
return b;
}
return pow (2, n) * b;
}
// stein算法
int stein (int a, int b){
if (a == b){
return a;
}
if(a % 2 == 0){
if (b % 2 == 0){
return 2 * stein(a/2, b/2);
}else{
return stein(a/2, b);
}
}else{
if (b % 2 == 0){
return stein(a, b/2);
}else{
return stein((int)fabs(a - b) / 2, (a + b) / 2);
}
}
}
// 测试模块:通过传入函数的编号,测试对应函数模块并返回运行时间
double test(int n){
int i;
clock_t start,end;
int a[10][2]={{2,4},{24,36},{45,12332},{456,235464},{5534555,545},{676,68},{12,124464640},{10046500,50},{45645,4234},{234,8}};
start = clock();
switch(n){
case 1 :
for(i = 0; i < 10; i++){
int t = divsion1(a[i][0], a[i][1]);
printf("%d,%d的最大公约数为:%d,最小公倍数为:%d\n",a[i][0], a[i][1], t, a[i][0]*a[i][1] / t);
}
end = clock();
break;
case 2:
for(i = 0; i < 10; i++){
int t = divsion2(a[i][0], a[i][1]);
printf("%d,%d的最大公约数为:%d,最小公倍数为:%d\n",a[i][0], a[i][1], t, a[i][0] *a [i][1] / t);
}
end = clock();
break;
case 3:
for(i = 0; i < 10; i++){
int t = enumComputing(a[i][0], a[i][1]);
printf("%d,%d的最大公约数为:%d,最小公倍数为:%d\n",a[i][0], a[i][1], t, enumMinMultiple(a[i][0], a[i][1]));
}
end = clock();
break;
case 4:
for(i = 0; i < 10; i++){
int t = getMinMultiple(a[i][0], a[i][1]);
printf("%d,%d的最大公约数为:%d,最小公倍数为:%d\n",a[i][0], a[i][1], t, a[i][0] * a[i][1] / t);
}
end = clock();
break;
case 5:
for(i = 0; i < 10; i++){
int t = stein(a[i][0], a[i][1]);
printf("%d,%d的最大公约数为:%d,最小公倍数为:%d\n",a[i][0], a[i][1], t, a[i][0] * a[i][1] / t);
}
end = clock();
break;
}
return (double) (end-start)/CLOCKS_PER_SEC;
}
int main(void){
int n;
while(1){
printf("输入调用哪种求解最大公约数的函数函数编号:");
scanf("%d",&n);
printf("\n运行时间为:%lfseconds\n\n",test(n));
}
return 0;
}