目前有三种常用的求两个数的最大公约数的方法:
1. 欧几里得算法
2. 连续整数检测算法
3. 分解质因数算法
1.1 更相减损法
可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之
判断是否存在偶数,如果有,则先除以二,然后大数减小数,差和小的那个数比较,仍然是较大的减较小的,(中间如果遇到偶数要除以二),求到最后会留下两数相等,这个数乘上以前消掉的几个2就是所求最大公约数。
1.2 欧几里得算法(辗转相除法)
相当于更相减损法的加速版本,一次一次减速度太慢,干脆互相求余,其思路是不论奇偶,互相求余,再用余数和第二个数比较,直到余数为0时,这个计算式的除数就是最大公约数。
在这里给出伪码:
输入m,n;
r=m%n;
循环直到r=0
{
m=n;
n=r;
r=m%n;
}
输出n;
c++代码如下:
int GCD(int m, int n)
{
int r;
r = m%n;
while (r != 0)
{
m = n;
n = r;
r = m%n;
}
return n;
}
当然了与之对应的也有递归算法
int GCD(int m, int n)
{
return m%n ? GCD(n, m%n) : n;
}
1.3 Stein算法
这个纯粹是百度时才了解的算法
和欧几里得算法对比:
欧几里德算法每次迭代中最恶劣的情况是,a=2b-1,这样,迭代后,r=b-1。如果a小于2^N,这样大约需要4N次迭代。而Stein算法,每次迭代后,显然AN+1BN+1≤ ANBN/2,最大迭代次数也不超过4N次。也就是说,迭代次数几乎是相等的。但是,需要注意的是,对于大素数,试商法将使每次迭代都更复杂,因此对于大素数,Stein算法将更有优势。
下面是该算法百度链接:
http://baike.baidu.com/link?url=pbdVnxbHhWYY3wW0KfDBUwK16s1-X2N-zCfci6Un2z0Ae0tkoFjuH3Z5e3pm8o-fiVroAMrFuijzrfY_vs9cZJlqv-nkWi3tW3EwLX-DpIm
代码源自百度百科
#define CHECK(a) (!(1 & (a)))//判断是否被2整除
#define CLEAN2(a) while (CHECK(a))a = a >>= 1//移除非公因子的2
#define BIGERA if(a<b)(t = a, a = b, b = t)//取较大的数为a
int gcd(int a, int b){
int c_2 = 0, t;
while ((CHECK(a)) && (CHECK(b))){
a = a >>= 1; b = b >>= 1; c_2++;
}
CLEAN2(a);
CLEAN2(b);
BIGERA;
while (a = ((a - b) >> 1)){
CLEAN2(a);
BIGERA;
}
return b << c_2;
}
2.1 连续整数检测算法
int GCD(int m, int n)
{
int a;
if (m>n)
a = n;
else
a = m;
while (a)
{
if (m%a == 0 && n%a == 0)
{
break;
}
else a = a - 1;
}
return a;
}
3. 1 分解质因数算法
把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是这几个数的最大公约数。
if (m<n)
{
swap(m, n);
}
int a = m%n;
while (a!= 0)
{
m = n;
n = a;
a = m%n;
}
return n;
3.2 短除法
先用这几个数的公约数连续去除,一直除到所有的商互质为止,然后把所有的除数连乘起来,所得的积就是这几个数的最大公约数。