1、辗转相除法,因为(x,y)的公约数可以通过下面的分析求得,x可以表示为ky + b,那么(x,y)的公约数可以表示为(ky+b,y)的公约数,也就变成(b,y)的公约数,而b=x % y,且b <=y,这样可以递归调用(y,b)(b,y%b) ...直到y%b ==0为止。
2、既然ky+b 与y有相同的最大公约数,那么如果x>y,(x-y,y)和(x,y)的最大公约数也是相同的,这样不断递归下去直到x==y,可以求得最大公约数代码如下:
#include <stdio.h>
int GreatestCommonDivisor(int value1, int value2) {
int tmp = value1 % value2;
if (tmp == 0) {
return value2;
} else {
return GreatestCommonDivisor(value2, tmp);
}
}
int GreatestCommonDivisor1(int value1, int value2) {
if (value1 > value2) {
return GreatestCommonDivisor(value1 - value2, value2);
} else if(value1 == value2) {
return value1;
} else {
return GreatestCommonDivisor(value1, value2 - value1);
}
}
int main(int argc, char** argv) {
int value1 = 4;
int value2 = 7;
printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor(value1, value2));
printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor1(value1, value2));
}
3、前两种方法,都有一些缺点,辗转相除方法虽然递归的次数比较少,但计算模的代价比较大,而相减法虽然计算代价相对小,但有些情况下递归的次数非常大,因此方法3将两种策略结合起来,分一下几种情况处理:
1)如果x,y都是偶数,那么一定有一个公因子2,然后将x,y都除以二,即左移1位,再递归求公因子
2)如果x,y一个奇数,一个偶数,那么偶数除以2(左移1位)后,再递归求公因子是一样的
3)如果x,y都是奇数,使用相减法递归求公因子
具体代码如下:
#include <stdio.h>
int GreatestCommonDivisor(int value1, int value2) {
int tmp = value1 % value2;
if (tmp == 0) {
return value2;
} else {
return GreatestCommonDivisor(value2, tmp);
}
}
int GreatestCommonDivisor1(int value1, int value2) {
if (value1 > value2) {
return GreatestCommonDivisor(value1 - value2, value2);
} else if(value1 == value2) {
return value1;
} else {
return GreatestCommonDivisor(value1, value2 - value1);
}
}
bool IsEven(int value) {
return (value & 0x01) != 1;
}
int GreatestCommonDivisor2(int value1, int value2) {
int greatest_common_divisor = 1;
if (IsEven(value1) && IsEven(value2)) {
if (value1 >0 && value2 >0) {
greatest_common_divisor *=2;
greatest_common_divisor *= GreatestCommonDivisor2(value1>>1, value2>>1);
} else {
return 1;
}
} else if (IsEven(value1)) {
if (value1 > 0) {
greatest_common_divisor *= GreatestCommonDivisor2(value1>>1, value2);
} else {
return 1;
}
} else if(IsEven(value2)) {
if (value2 >0) {
greatest_common_divisor *= GreatestCommonDivisor2(value1, value2>>1);
} else {
return 1;
}
} else {
if (value1 > value2) {
greatest_common_divisor *= GreatestCommonDivisor2(value1 - value2, value2);
} else if (value1 < value2) {
greatest_common_divisor *= GreatestCommonDivisor2(value1, value2 - value1);
} else {
greatest_common_divisor *= value1;
}
}
return greatest_common_divisor;
}
int main(int argc, char** argv) {
int value1 = 13;
int value2 = 65;
printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor(value1, value2));
printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor1(value1, value2));
printf("the greatest common divisor of %d and %d is %d\n", value1, value2, GreatestCommonDivisor2(value1, value2));
}
参考文献:
编程之美2.7