用二进制方法求两个整数的最大公约数(GCD)

时间:2021-12-07 00:33:31

二进制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算法需要用除法,这在某些嵌入式系统中可能排上用场。

 

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

 

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));

}
}