最大公约数(Greatest Common Divisor, GCD)的计算是很多问题中比较关键的一个步骤,所以如何快速的计算最大公约数比较关键。本文将《编程的本质》中第五章中最大公约数的问题稍微总结一下。
1. 暴力破解法。只是我们在无可奈何时的方法,但是请不要忽略它,可能在变量数少,维度低等条件下,它的运行效率也不会很低。而且,有时候我们需要一个Quick-Dirty的实现,在后续过程中慢慢更新即可。
2. 欧几里德算法。这个算法比较经典,基本每个讲解GCD的书中都会讲解这个知识。其主要利用如下两个性质:
- GCD(a, a) = a
- GCD(a, b) = GCD(a-b, b)
- GCD(a, b) = GCD(b, a)
while (a != b)
{
if (a < b)
b = b - a;
else if ( a > b)
a = a - b;
}
return a;
3. Stein算法,Stein更新了传统的方法,其本质上是发现了一些规律使得GCD算法执行速度更快。
- GCD(2a, 2b) = 2GCD(a, b)
- GCD(2a, 2b+1) = GCD(a, 2b+1)
- GCD(2a+1, 2b) = GCD(2a+1, b)
- GCD(2a+1, 2b+1) = GCD(2b+1, a-b)
int factor = 1;
while (a != b)
{
while (!(a & 0x1) || (b & 0x1))
{
// change to 2*GCD(a/2, b/2)
a>>1;
b>>1;
factor<<1;
}
if (!(a & 0x1))
{
// change to GCD(a/2, b)
a>>1;
}
else if (!(b & 0x1))
{
// change to GCD(a, b/2)
b>>1;
}
else
{
// change to GCD (b, a - b)
a ^= b;
b ^= a;
a ^= b;
b = b - a;
}
if (a < b)
b = b - a;
else if ( a > b)
a = a - b;
}
return a * factor;
在编写求最大公约数的时候,一般的算法都假设输入两个数是正数,对于负数需要做简单的处理即可,即将参数变化下重新调用基于正数的。
本文完。