Loading [MathJax]/jax/output/HTML-CSS/jax.js

Tuesday, June 17, 2014

a bit of number theory: Greatest Common Divisor

We'll discuss one of the most ancient algorithm in the history of Number Theory. 

Problem Statement:
Given two positive integers M and N, find the greatest integer D such that D divides both M and N.

In case you have forgotten, here are a few examples:

  • for M=10, N=55, the greatest common divisor D is 5
  • for M=72, N=64, the greatest common divisor D is 8
For small (M,N), D can usually be easily found by trial and error (and sometimes by terror), but for large values of (M,N), while trying all integers less than M and N might work, it can be really slow and certainly we can do better than this.

An efficient algorithm to solve this problem hinges on the following observation:
Theorem 1:
For positive integers a,b,d, if da and db, then dax+by for any x,yZ.

Proof:
Directly substituting a=kd and b=ld shows that the claim indeed holds.

With this, we can devise an efficient algorithm due to Euclid:

Euclid(M,N)
Input: M,N are integers, MN
Output: integer D, the greatest common divisor of M and N
Pseudo-code:
if N==0:
   return M
return Euclid(N, M(modN))

Convince yourself that this algorithm works.
Euclid(M,N) eventually terminates with D=xM+yN for some x,yZ.
We will prove that it indeed returns the greatest common divisor of M and N.

Theorem 2:
Given integers d,x,y,a,b, if d=ax+by and d divides both a and b, then d is the greatest common divisor of a and b.

Proof:
Suppose that d is not the greatest common divisor of a and b. Hence there is D where D>d such that D divides both a and b. By Theorem 1, Dax+by=d, which implies that Dd, a contradiction. Hence d must be the greatest common divisor of a and b.

Finally, what is the running time of Euclid(M,N)? It is guaranteed that Euclid(M,N) will terminate after O(logN) recursive calls since each call reduces the size of either M or N by half, with each call performs a modular arithmetic which can be done in constant time. The claim below explains the upper bound to the recursive call.

Claim:
If MN, then M(modN)<M2 

Proof:
N can be either bigger or less than M2, so we have 2 cases to consider:
Case 1: NM2
Then we know for a fact that M(modN)<NM2.
Case 2: N>M2
Here we have M(modN)MN(modN) and since MN<MM2=M2<N we have M(modN)=MN<M2.

Here is an implementation in C:
/* Recursive greatest common divisor */
int gcd(int M, int N){
   if (N>M) return gcd(N, M);
   if (N==0) return M;
   return gcd(N, M%N);
}

No comments:

Post a Comment