GCD : Greatest Common Divisor
Definition
GCD(Greatest Common Divisor) of two or more given numbers, not all zero, is the highest possible number which divides them all.
Lets see how we can code it in different ways.
Prime factorization
Its as per the definition and discussed above. So, one can say, let and be the two numbers with unique prime factorization given as\
Here are a few examples.
Find the GCD of 36 and 24.
Lets do the prime factorization of both the numbers, 36 and 24.
Find the GCD of 15, 21 and 6.
Again, start by prime factorization of all the given numbers.
I will cover the factorization code and what are the efficient ways to do so in another article.
Euclid’s algorithm
The Euclid’s algorithm says that the GCD of two numbers does not change if the larger number is replaced by its difference with the smaller number. Alternatively, the gcd of two numbers also divides their difference.
I will cover Euclid’s algorithm and Extended Euclid’s algorithm in another article. For time being just remember the following rules.
Following the above definition one can say\
After all, ’s greatest divisor is itself, which is also divisor of zero.
Lets convert this into some code,
Iterative Code
/**
* An iterative function to return the GCD of two numbers
*
* @param a
* first number
* @param b
* second number
* @return gcd of a & b
*/
public static int iterativeGCD(int a, int b) {
if (a == 0) {
return b;
} else if (b == 0) {
return a;
}
while (a != b) {
if (a > b) {
a = a - b;
} else {
b = b - a;
}
}
return a;
}
Recurvive Code
/**
* A recursive function to return the GCD of two numbers
*
* @param a
* first number
* @param b
* second number
* @return gcd of a & b
*/
public static int recursiveGCD(int a, int b) {
if (a == 0) { // Case 1
return b;
} else if (b == 0) { // Case 2
return a;
}
if (a == b) { // Case 3
return a;
}
if (a > b) { // Case 4
return recursiveGCD(a - b, b);
} else { // Case 5
return recursiveGCD(a, b - a);
}
}
Running an example for and we obtained the on 8th iteration.
When | A | B |
---|---|---|
Before 1st iteration | 420 | 96 |
After 1st iteration | 324 | 96 |
After 2nd iteration | 228 | 96 |
After 3rd iteration | 132 | 96 |
After 4th iteration | 36 | 96 |
After 5th iteration | 36 | 60 |
After 6th iteration | 36 | 24 |
After 7th iteration | 12 | 24 |
After 8th iteration | 12 | 12 |
Faster Euclid’s Algorithm
One can look at another definition for Euclid’s Algorithm, which is as follows
The code for the above is simple
Iterative Code
/**
* A faster iterative function to return the GCD of two numbers
*
* @param a
* first number
* @param b
* second number
* @return gcd of a & b
*/
public static int iterativeFasterGCD(int a, int b) {
while (a != 0 && b != 0) {
if (a > b) {
a = a % b;
} else {
b = b % a;
}
}
return Math.max(a, b);
}
Recurvive Code
/**
* A faster recursive function to return the GCD of two numbers
*
* @param a
* first number
* @param b
* second number
* @return gcd of a & b
*/
public static int recursiveFasterGCD(int a, int b) {
if (a == 0) { // Case 1
return b;
} else if (b == 0) { // Case 2
return a;
}
if (a == b) { // Case 3
return a;
}
if (a > b) { // Case 4
return recursiveGCD(a % b, b);
} else { // Case 5
return recursiveGCD(a, b % a);
}
}
Running the same example for and we obtained the on 4th iteration.
When | A | B |
---|---|---|
Before 1st iteration | 420 | 96 |
After 1st iteration | 36 | 96 |
After 2nd iteration | 36 | 24 |
After 3rd iteration | 12 | 24 |
After 4th iteration | 12 | 0 |
Why using mod is faster ?
Notice in normal Euclid’s algorithm, that we subtracted ’s value from ’s four times before became less than . The same effect results from replacing ’s value by . (In this case, ) Using this approach forces us to change the loop condition, however, as here what will eventually happen is that one of or will become zero. (Indeed, is impossible to arrive at unless )
One Liner- Wait, What?
Tadda!!! What kind of sorcery is this, right? Why the hell I am telling you this right now? Well, its not new its same as above two algorithms. Two things to keep in mind, one . Another observation is whatever be the case or , it doesn’t matter, we will be swapping the values on each recursive call and eventually we will reach the solution.
Now, don’t ask me everything why it will work, just take a pen paper and write down the values in each iteration.
/**
* A recursive function to return the GCD of two numbers
*
* @param a
* first number
* @param b
* second number
* @return gcd of a & b
*/
public static int gcd(int a, int b) {
return a == 0 ? b : gcd(b % a, a);
}
Stein’s Algorithm : Binary method
This method relies on the fact that for two non-negative integers we can compute GCD by only using subtraction and division by 2. There are five cases which needs to be implemented.
Note : Multiplication and division by can be done with bitwise operation.
If
If
If
If
If
/**
* A recursive function to return the GCD of two numbers
*
* @param a
* first number
* @param b
* second number
* @return gcd of a & b
*/
public static int gcd(int a, int b) {
if (b == 0) return a;
if (a == 0) return b;
// a and b even
if ((a & 1) == 0 && (b & 1) == 0) return gcd(a >> 1, b >> 1) << 1;
// a is even, b is odd
else if ((a & 1) == 0) return gcd(a >> 1, b);
// a is odd, b is even
else if ((b & 1) == 0) return gcd(a, b >> 1);
// a and b odd, a >= b
else if (a >= b) return gcd((a - b) >> 1, q);
// a and b odd, a < b
else return gcd(a, (b - a) >> 1);
}
Time Complexity:
where is the number of bits in the larger number.
Or the total number of steps is at most the sum of the numbers of bits of a and b. Since subtracting two numbers smaller than a and b costs bit operations.
Leave a Comment
Your email address will not be published. Required fields are marked *