user7062534
user7062534

Reputation:

How to use Euclid's algorithm to find GCF/GCD?

I have created a method that allows me to find the GCF/GCD of two numbers, and although I have a working code, I don't know how or why it works. I understand Euclid's algorithm, but am not sure how the following snippet uses it.

private int gcd(int a, int b) 
  {
  if (b == 0) 
     return a; 
  else if(a ==0) 
     return b;
  else
     return gcd(b, a % b);

  }

I am especially confused on what it is returning, because why are were returning two values? And what does the a % b do? How does this use Euclid's algorithm?

Upvotes: 0

Views: 2396

Answers (3)

danyamachine
danyamachine

Reputation: 1908

"the greatest common divisor of two numbers does not change if the larger number is replaced by its difference with the smaller number."

(wikipedia - Euclidean algorithm)

So, modulo:
Modulo returns the remainder of the integer divison between two integers. Integer division is divison without fractions or floating points. Let's denote integer division as m /\ n.

m /\ n = o;  
m % n = p;  
o * n + p = m;  

As an example,

29 /\ 3 = 9; (3 goes - whole - into 29 9 times)  
29 % 3 = 2; (the integer division of 29 into 3 has a remainder of 2)  
9 * 3 + 2 = 29; (9 goes into 29 3 times (and 3 goes into 29 9 times), with a remainder of 2)  

Note that if m is smaller than n (i.e. m < n), then n goes into m 0 times (m /\ n = 0), so the remainder of the integer division will be m (m % n = m, because o * n + p = m and so (0*n) + p = 0 + p = p = m);

So, how does the function work? let's try using it.

1 - gcd(m, n), m < n
So, if we start out gcd(m, n) with an m that is smaller than n, the only thing that happens on the next nested call to gcd is that the order of the arguments changes: gcd(n, m % n) = gcd(n, m);

2 - gcd(n, m), m < n
Okay, so now the first argument larger than the second.
According to euclid's algorithm, we want to do something to the larger of the two numbers. We want to replace it with the difference between it and the smaller number. We could do m - n a bunch of times. But what m % n does is the exact same as subtracting n from m as many times as possible before doing so would result in a negative number. Doing a subtraction would look like (((m - n) - n) - n) - n) and so on. But if we expand that out, we get: m - (n * o). Because o * n + p = m, we can see that m - (n * o) = p and p = m % n. So, repeatedly subtracting the smaller from the larger is the same as doing modulo of the larger with the smaller.
In the next step, the second argument may be 0 (if n was a divisor of m). In this case, the function returns n. this is correct because n is a divisor of itself and also, as we've seen, a divisor of m.
Or, the second argument may be smaller than n. That is because the remainder of the integer divison of m into n must be smaller than n - this is because, if the remainder of the division were larger than n, then n could have fit into m one more time, which it didn't; this is an absurd result. Assuming that n is not 0, then the second argument (let's call it p) is smaller than n.
So, we are now calling gcd(n, p), where p < n.

3 - gcd(n, p), p < n
What happens now? well, we are exactly in the same place as we were in the previous paragraph. Now we just repeat that step, i.e. we will continue to call gcd(a, b), until the smaller of the two numbers that are passed into gcd(a ,b) is a divisor of the larger of the two numbers, (meaning that a % b = 0) in which case you simply return the smaller of the two numbers.

Upvotes: 1

Frelling
Frelling

Reputation: 3507

Given that your question has a few components, I’ll discuss the evolution of Euclid’s classical algorithm into the recursive method you presented. Please note that the methods presented here assume that a >= b

The method below most likely implements the algorithm that you are familiar with, which repeatedly subtracts b (the smaller number) from a (the larger number), until it is no longer larger or equal to b. If a == 0, there is no remainder, giving b as the GCD. Otherwise, the values of a and b are swapped and repeated subtraction continues.

public int classic_gcd(int a, int b) {
    while (true) {
        while (a >= b)
            a = a - b;

        if (a == 0)
            return b;

        int c = b;
        b = a;
        a = c;
    }
}

Since the inner while loop, essentially calculates the reminder of a divided by b, it can be replaced with the modulus operator. This greatly improves the convergence rate of the algorithm, replacing a potentially large number of subtractions with a single modulus operation. Consider finding the GCD of 12,288 and 6, which would result in over 2,000 subtraction. This improvement is shown in the modified method below.

public int mod_gcd(int a, int b) {
    while (true) {
        int c = a % b;
        if (c == 0)
            return b;

        a = b;
        b = c;
    }
}

Lastly, the modified algorithm can be expressed as a recursive algorithm, that is, it calls upon itself, as follows:

public int recurse_gcd(int a, int b) {
   if (b == 0)
       return a;
   else
       return recurse_gcd(b, a % b);
}

This method accomplishes the same as before. However, rather than looping, the method calls itself (which if not checked is an endless loop too). The swapping of values is accomplishing by changing the order of the arguments passed to the method.

Mind you, the methods above are purely for demonstration and should not be used in production code.

Upvotes: 0

Trung Duong
Trung Duong

Reputation: 3475

1) What does the a % b do?
% is the modulus or remainder operator in Java. The % operator returns the remainder of two numbers. For example 8 % 3 is 2 because 8 divided by 3 leaves a remainder of 2.

2) The Euclidean algorithm is based on the principle that the greatest common divisor of two numbers does not change if the larger number is replaced by its difference with the smaller number. Actually, your gcd function is used a more efficient version of the Euclidean algorithm. This version instead replacing the larger of the two numbers by its remainder when divided by the smaller of the two (with this version, the algorithm stops when reaching a zero remainder). This was proven by Gabriel Lamé in 1844 (https://en.wikipedia.org/wiki/Euclidean_algorithm)

3) Your gcd function's not returning two values, it's a recursive function. The recursive function is a function which either calls itself or is in a potential cycle of function calls. In case of your gcd function, it will be repeat until one of two parameters become zero and the gcd value is the remain parameter.
You could learn more about recursive function at this link.
http://pages.cs.wisc.edu/~calvin/cs110/RECURSION.html

Upvotes: 0

Related Questions