バイナリユークリッドの互除法の実装
投稿日: 更新日:
バイナリユークリッドの互除法とは
ユークリッドの互除法では剰余演算%
を使いますが、これは他の演算に比べ重たいです。
そこで、コンピュータが2進数で処理していることを利用して、シフト演算やビット演算で高速化する手法です。
アルゴリズム
非負整数の最大公約数を求める関数gcd
です。
- の場合を返す。
- もも偶数の場合 → を返す。
- のみ偶数の場合 → を返す。
- のみ偶数の場合 → を返す。
- もも奇数の場合 → を返す。
の時、が成り立つことを利用しています。
実装
偶奇の判定は&1
で、2で割るのは>>1
で処理しています。
int gcd(int a, int b){
if(a == 0)return b;
if((a&1) == 0 && (b&1) == 0){
return 2 * gcd(a>>1, b>>1);
}
if((a&1) == 0){
return gcd(a>>1, b);
}
if((b&1) == 0){
return gcd(a, b>>1);
}
return gcd(abs(a-b)>>1, min(a, b));
}
非再帰化
template<typename T>
T gcd(T a, T b){
if(a == 0)return b;
if(b == 0)return a;
T s = a;
T t = b;
int cnt = 0;
while(a != 0){
if(s&1 == 0 && t&1 == 0){
cnt++;
a = s>>1;
b = t>>1;
}else if(s&1 == 0){
a = s>>1;
}else if(t&1 == 0){
b = t>>1;
}else{
a = abs(s-t)>>1;
b = min(s, t);
}
}
return b << cnt;
}