12 minutes read

Many people, hearing the word "algorithm", think about something relatively novel and non-existent before the modern computer era. But one of the most widely used algorithms in today's world (crucial, for example, in cryptographic applications) is, in fact, two thousand years old. A famous computer scientist Donald Knuth called it "the granddaddy of all algorithms". This algorithm was described by an ancient Greek mathematician Euclid and finds the greatest common divisor of two integers. Let's see how it works!

Division with remainder

Firstly, let's recall the procedure known as a division with remainder. Suppose we have two integers aa and bb, such that b0b \neq 0. Marking all multiples of bb on a number line, we see that aa either coincides with one of them or lies between two marks. If bqbq is the closest mark to the left from aa (possibly coinciding with aa itself), the "distance" rr from bqbq to aa is strictly less than bb.

Division with remainder

Keeping in mind this picture, we may state the following:

For any integer aa and any non-zero integer bb, there exist uniquely determined integers qq and rr, such that

a=bq+r,0r<qa = bq + r, \quad 0 \leq r < qWe will say that aa divided by bb has quotient qq and remainder rr. We will also denote rr as amodba \bmod b. Notice that q=a/bq = \lfloor a / b\rfloor, meaning "the greatest integer that is less or equal to a/ba / b " (where a/ba / b is a floating-point result of ordinary division).

For example, 239=1023+9239 = 10 \cdot 23 + 9, so 239239 divided by 1010 has a remainder 99 (and we can write that 239mod10=9239 \bmod 10 = 9).

Quotient  and remainder

Euclid's algorithm

Suppose now we want to find the greatest common divisor of two integers aa and bb. Somebody can think the most obvious approach to compute gcd(a,b)\gcd(a, b) is to firstly represent aa and bb as products of primes, and then multiply together their common factors. For instance, 15660=223352915660 = 2^{2} \cdot 3^{3} \cdot 5 \cdot 29 and 3393=3213293393 = 3^{2} \cdot 13 \cdot 29, so their greatest common divisor is 3229=2613^{2} \cdot 29 = 261.

However, despite centuries of effort, nobody has invented an efficient algorithm for factoring. Is there some other way to compute the greatest common divisors? Fortunately, yes. The key fact is that

If aa andbb are positive integers, and aba \geq b, then gcd(a,b)=gcd(b,amodb)\gcd(a, b) = \gcd(b, a \bmod b)

Why is it true? Well, if a=bq+ra = bq + r, then amodb=r=aqba \bmod b = r = a - qb, so necessarily any integer that divides both aa and bb must divide amodba \bmod b. On the other hand, any integer that divides both amodba \bmod b and bb must also divide aa. So, as the sets of all common divisors coincide, the greatest common divisors also coincide.

Hence we can easily write a recursive algorithm, always coming down to smaller arguments until one of them is zero (and you can easily prove that gcd(a,0)=a\gcd(a, 0) = a for any positive integer aa). Applying it to a=210a = 210 and b=196b = 196, for example, we obtain

gcd(210,196)=gcd(210mod196,196)=gcd(14,196)=gcd(14,196mod14)=gcd(14,0)=14\gcd(210, 196) = \gcd(210 \bmod 196, 196) = \gcd(14, 196) = \gcd(14, 196 \bmod 14) = \gcd(14, 0) = 14Is it really an efficient algorithm? For the answer, we need to understand how quickly the arguments aa and bb decrease with each recursive call. In a single round, the pair of arguments (a,b)(a, b) becomes (b,amodb)(b, a \bmod b). Either b>a/2b > a/2 and then amodb=ab<aa/2=a/2a \bmod b = a - b < a - a/2 = a/2Otherwise, ba/2b \leq a/2 and then, as amodb<ba \bmod b < b, it follows that amodb<ba/2a \bmod b < b \leq a /2In the next round, (b,amodb)(b, a \bmod b) will become (amodb,bmod(amodb))(a \bmod b, b \bmod (a \bmod b)). Here, we always write the greatest of two arguments in the first place. So, after any two consecutive rounds of the algorithm, the greatest of two arguments is at the very least halved in value. That means we will reach zero in at most 2log2a2 \log_{2} a divisions, which is quite fast — for a 24-digit aa (in our ordinary decimal system), there will be less than 170 divisions.

Extended Euclid's algorithm

Tweaking Euclid's algorithm a bit allows us to express gcd(a,b)\gcd(a, b) as an integer linear combination of aa and bb, that is, in the form

gcd(a,b)=ax+by\gcd(a, b) = ax + bywhere xx and yy are some integers. Such a representation is always possible and will help us to do division in modular arithmetic (an operation making possible, for example, the key generation in the famous RSA cryptosystem).

Before giving the general algorithm, we illustrate it with an example. We will compute gcd(2024,748)\gcd(2024, 748): 2024=7482+528748=5281+220528=2202+88220=882+4488=442+02024 = 748 \cdot 2 + 528\\ 748 = 528 \cdot 1 + 220\\ 528 = 220 \cdot 2 + 88\\ 220 = 88 \cdot 2 + 44\\ 88 = 44 \cdot 2 + 0We can look at the second line from below and write:44=22088244 = 220 - 88 \cdot 2Then, looking one line up, we notice we can substitute 8888 with an expression 5282202528 - 220 \cdot 2, so:44=220(5282202)2=2205528244 = 220 - (528 - 220 \cdot 2) \cdot 2 = 220 \cdot 5 - 528 \cdot 2Next, we substitute 220220 with 748528748 - 528, hence: 44=(748528)55282=7485528744 = (748 - 528) \cdot 5 - 528 \cdot 2 = 748 \cdot 5 - 528 \cdot 7See the pattern? In the end (check it!) we obtain:44=2024(7)+7481944 = 2024 \cdot (-7) + 748 \cdot 19Proceeding in the same way, we can always express d=gcd(a,b)d = \gcd(a, b) in the form d=ax+byd = ax + by, where xx and yy are integers — in other words, as a linear combination of aa and bb. This process can be implemented as a recursive algorithm. Suppose we know the coefficients xx' and yy' in the representation of dd as d=bx+(amodb)yd = bx' + (a \bmod b)y'? Now we can obtain the coefficients xx and yy in the representation d=ax+byd = ax + by. Since amodb=abqa \bmod b = a - bq with q=a/bq = \lfloor a / b \rfloor,

d=bx+(amodb)y=bx+(abq)y=ay+b(xqy)d = bx' + (a \bmod b)y' = bx' + (a - bq)y' = ay' + b(x' - qy')So, x=yx = y' and y=xa/byy = x ' - \lfloor a / b \rfloor y'. The base case for this recursion is again b=0b = 0, when d=a=a1+b0d = a = a \cdot 1 + b \cdot 0.

Working with non-positive integers

In the previous paragraphs, we discussed finding gcd\gcd only when one integer is strictly positive and another is at least non-negative (the case when it is zero was considered as the base of the recursion). How can we handle negative numbers? Firstly, we notice that flipping the sign of any argument doesn't change the greatest common divisor, so we can always reduce the problem to finding gcd\gcd of two non-negative integers. And then the only case not mentioned before is gcd(0,0)\gcd(0, 0). Well, there exists a somewhat counterintuitive convention that gcd(0,0)=0\gcd(0, 0) = 0. Now we can use Euclid's algorithm to find gcd\gcd of any two integers.

Conclusion

In this module, we have explored one of the most important algorithms called Euclid's algorithm. Here are the main take-aways:

  • Euclid's algorithm is an effective algorithm for finding the greatest common divisor of two integers.
  • It can be written in a recursive way and consists in replacing the greatest of two positive arguments with its remainder modulo another argument
  • An extended version of Euclid's algorithm allows us to represent gcd\gcd of two integers as their linear combination.
3 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo