经典算法(3)- 用二进制方法求两个整数的最大公约数(GCD)

二进制GCD算法基本原理是:
 先用移位的方式对两个数除2,直到两个数不同时为偶数。然后将剩下的偶数(如果有的话)做同样的操作,这样做的原因是如果u和v中u为偶数,v为奇数, 则有gcd(u,v)=gcd(u/2,v)。到这时,两个数都是奇数,将两个数相减(因为gcd(u,v) = gcd(u-v,v)),得到的是偶数t,对t也移位直到t为奇数。每次将最大的数用t替换。


二进制GCD算法优点是只需用减法和二进制移位运算,不像Euclid's算法需要用除法,这在某些嵌入式系统中可能排上用场。

本例实现参考了<<计算机编程的艺术>>(Knuth)第二卷中介绍的算法。

/**
 * 
 * @author ljs 2011-5-18
 * 
 * solve gcd using binary method 
 * @see also "The Art of Computer Programming, Vol2"
 *
 */
public class GCD_Binary {
	/**
	 * solve gcd using binary method
	 * @param u
	 * @param v
	 * @return gcd(u,v)
	 */
	public static int gcdBinary(int u,int v){
		u=(u<0)?-u:u;
		v=(v<0)?-v:v;
		
		if(u==0)
			return v;
		if(v==0)
			return u;
		
		int k=0;
		while((u & 0x01)==0 && (v & 0x01) == 0){
			u>>=1; //divide by 2
			v>>=1;
			k++;
		}
		//at this time, there is at least one number is odd between m and n
		int t=-v; //set it negative for later comparison of (t>0)
		if((v & 0x01)==1){
			//v is odd
			t = u;
		}
		//process t as a possible even number
		while(t != 0){
			while((t & 0x01)==0){
				//do until t is not even 
				t>>=1;
			}
			if(t>0) //u > v (the max is replaced by |t|)
				u=t; 
			else //u<v (the max is replaced by |t|)
				v=-t;
			//now u and v are all odd, then u-v is even
			t = u-v;
		}
		return u*(1<<k);
	}
	
	public static void print(int m,int n,int gcd){
		m = (m<0)?-m:m;
		n = (n<0)?-n:n;
		System.out.format("gcd of %d and %d is: %d%n",m,n,gcd);
	}
	
	public static void main(String[] args) {
		int m = -18;
		int n= 12;
		print(m,n,gcdBinary(m,n));
		
		//co-prime
		m = 15;
		n= 28;
		print(m,n,gcdBinary(m,n));
				
		m = 6;
		n= 3;
		print(m,n,gcdBinary(m,n));
		
		m = 6;
		n= 3;
		print(m,n,gcdBinary(m,n));
		
		m = 6;
		n= 0;
		print(m,n,gcdBinary(m,n));
		
		m = 0;
		n= 6;
		print(m,n,gcdBinary(m,n));
		
		m = 0;
		n= 0;
		print(m,n,gcdBinary(m,n));
		
		m = 1;
		n= 1;
		print(m,n,gcdBinary(m,n));
		
		m = 3;
		n= 3;
		print(m,n,gcdBinary(m,n));
		
		m = 2;
		n= 2;
		print(m,n,gcdBinary(m,n));
		
		m = 1;
		n= 4;
		print(m,n,gcdBinary(m,n));
		
		m = 4;
		n= 1;
		print(m,n,gcdBinary(m,n));
		
		m = 10;
		n= 14;
		print(m,n,gcdBinary(m,n));
		
		m = 14;
		n= 10;
		print(m,n,gcdBinary(m,n));
		
		m = 10;
		n= 4;
		print(m,n,gcdBinary(m,n));
		
	
		m = 273;
		n= 24;
		print(m,n,gcdBinary(m,n));
		
		m = 120;
		n= 23;
		print(m,n,gcdBinary(m,n));		
		
	}
}

转载于:https://www.cnblogs.com/ljsspace/archive/2011/06/05/2073364.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值