关于最大公约数有最经典的欧几里得算法,下面对欧几里得算法进行基本证明:
假设用f(x,y)表示x y的最大公约数,取k=x/y,b=x%y,则x=ky+b,如果一个整数能够同时整除x和y,则必能同时整除b和y,能 够同时整除b和y的数也必能同时整除x和y,即x和y的最大公约数和b和y的最大公约数是相同的,即有f(x,y)=f(y,x%y) (x>=y>0),如此处理便可把原问题转化为求两个更小的数的最大公约数,直到其中一个数为0,剩下的另外一个数就是两者的最大公 约数,则直接用递归实现
然而取模在计算机中是非常昂贵的开销,尤其对超过2的64次方的大整数而言,那代价更是昂贵,即便改写成非递归的形式从而达到取消递归过程带来的额外资源消耗,采用欧几里得算法也不容乐观。因此应该想办法把取模运算去除。如果一个数能够同时整除x和y,则必能够同时整除x-y,和y,而能够同时整除x-y和y的数,也必能够同时整除x和y,即x和y的最大公约数与x-y和y的最大公约数相同,即f(x,y)=f(x-y,y)
因此有下面的代码实现:
此算法有一个缺点就是如果要计算的两个数之间相差的数量级比较大,则算法实现的效率是很低的,例如gcd(2489124580, 4),可能要花数小时才能计算完。
微软面试心得中提供了更快捷的算法,原理如下:
原理:
1、f(x,y)=k*f(x1,y1);
2、如果x=p*x1,假设p是素数,并且y%p!=0,那么f(x,y)=f(p*x1,y)=f(x1,y)。
由此可得到算法为:不断的对x和y做除2操作,直至两者均不能被2整除,采用辗转相减法,获得一个可被2整除的数,继续做除2操作,循环,直至两数之一为0。详细描述如下:
若x,y均为偶数,f(x,y) = 2*f(x/2,y/2) = 2*f(x>>1,y>>1)
若x为偶数,y为奇数,f(x,y) = f(x/2,y) = f(x>>1,y)
若x为奇数,y为偶数,f(x,y) = f(x,y/2) = f(x,y>>1)
若x,y均为奇数,f(x,y) =f(y,x-y)
代码如下:
通过实验可知此算法的效率比第二种方法要高得多。
代码中用到的大整数的实现以及详细的最大公约数的算法我已上传,如想下载请点击下面的链接:
http://download.youkuaiyun.com/source/2397009 。