The Euclidean Algorithm and the Extended Euclidean Algorithm
On this page we look at the Euclidean algorithm and how to use it. We solve typical exam questions and show how to do the calculations by hand. We then look at how it can be adapted to find the modular inverse of a number and the extended Euclidean algorithm.
Contents
Recommended reading
- A Course in Computational Algebraic Number Theory by Henri Cohen
- The Art of Computer Programming, Volume 2: Seminumerical Algorithms by Donald E. Knuth
- Handbook of Applied Cryptography by Alfred J. Menezes, Paul C. van Oorschot and Scott A. Vanstone
- Elementary Number Theory by Gareth A. Jones and J. Mary Jones
Affiliate disclosure: we get a small commission for purchases made through the above links
- The Euclidean Algorithm
- Typical Exam Questions
- Bezout's identity
- Finding the modular inverse
- The Extended Euclidean Algorithm
- Computer programs
- References
- Contact us
- Comments
The Euclidean Algorithm
The Euclidean algorithm is an efficient method to compute the greatest common divisor (gcd) of two integers. It was first published in Book VII of Euclid's Elements sometime around 300 BC.
We write gcd(a, b) = d
to mean that d is the largest number
that will divide both a and b.
If gcd(a, b) = 1
then we say that a and b are coprime or relatively prime.
The gcd is sometimes called the highest common factor (hcf).
Algorithm: (Euclidean algorithm) Computing the greatest common divisor of two integers. (Ref: [MENE97], 2.104)
INPUT: Two non-negative integers a and b with
a ≥ b
.OUTPUT:
gcd(a, b)
.- While
b > 0
, do- Set
r = a mod b
, a = b
,b = r
- Set
- Return a.
The proof uses the division algorithm which states that for any two integers
a and b with b > 0
there is a unique pair of integers
q and r such that
a = qb + r
and 0 <= r < b
.
Essentially, a gets smaller with each step, and so, being a positive integer, it must eventually converge
to a solution (i.e. it cannot get smaller than 1).
If you have negative values for a or b, just use the absolute values |a|
and |b|
in the above algorithm.
By convention, if b = 0
then the gcd is a.
Python Code for GCD
1 def gcd(a, b): 2 """Compute the greatest common divisor (GCD) of a and b.""" 3 while b > 0: 4 a, b = b, a % b 5 return a 6 7 print(gcd(25, 5)) # 5 8 print(gcd(4, 9)) # 1 9 print(gcd(93, 219)) # 3 10 print(gcd(421, 111)) # 1
Typical Exam Questions
Every exam in number theory has a question on the Euclidean algorithm. They are a gift. Spend your last night before the exam practising it. Here's how we like to lay it out (the comments are just for guidance; they are not needed in a formal solution).
Question 1(a): Find gcd(421, 111).
Answer:
We use the Euclidean algorithm as follows:
421 = 111 x 3 + 88 | (larger number on left) |
111 = 88 x 1 + 23 | (shift left) |
88 = 23 x 3 + 19 | (note how 19 moves down the "diagonal") |
23 = 19 x 1 + 4 | |
19 = 4 x 4 + 3 | |
4 = 3 x 1 + 1 | (last non-zero remainder is 1) |
3 = 1 x 3 + 0 |
The last non-zero remainder is 1 and therefore gcd(421, 111) = 1.
At each step, take the larger number, divide by the other and then round down your answer to an integer value.
So 421 / 111 = 3.793
gives 3. Then find the remainder, 421 - 111 x 3 = 88
, so we can write out the
line as 421 = 111 x 3 + 88
. Repeat for the smaller number (111) until the remainder is zero.
The last non-zero remainder is the gcd, in this case 1.
(Once you have 1 as a remainder, the last line is not really necessary, but we keep it in for completeness.)
In our view, it really helps to be strict in how you lay out the solution. Otherwise you'll get flustered in an exam and make a mistake. Note how we always write each line with the quotient (111) on the left followed by the divisor (3). If you do that you always have the correct number ready to "shift left" to the other side on the next line.
Note how, if we lay it out this way, each number moves down a diagonal from top right to bottom left. This gives you a check as you go along.
421 = 111 x 3 + 88 111 = 88 x 1 + 23 88 = 23 x 3 + 19 23 = 19 x 1 + 4 19 = 4 x 4 + 3 4 = 3 x 1 + 1 3 = 1 x 3 + 0
Here's another example. Question 2(a): Find gcd(93, 219)
.
219 = 93 x 2 + 33
93 = 33 x 2 + 27
33 = 27 x 1 + 6
27 = 6 x 4 + 3
6 = 3 x 2 + 0
The last non-zero remainder is 3 and therefore gcd(93, 219) = 3.
Bezout's identity
Given any integers a and b, not both zero, there exist integers x and y such that
gcd(a, b) = xa + yb
In other words, you can always write gcd(a, b) as an integer combination of a and b.
Part (b) of most exam questions involve this. The question is usually of one of the forms
"Express1 = gcd(421,111)
as an integer combination", or
"Determine integers x and y such thatgcd(421, 111) = 421x + 111y
", or
"Determine a solution to the linear Diophantine equationgcd(421, 111) = 421x + 111y
".
For reference, here is the solution from part 1(a)
(1) 421 = 111 x 3 + 88 (2) 111 = 88 x 1 + 23 (3) 88 = 23 x 3 + 19 (4) 23 = 19 x 1 + 4 (5) 19 = 4 x 4 + 3 (6) 4 = 3 x 1 + 1 (7) 3 = 1 x 3 + 0
Question 1(b): Determine integers x and y such that gcd(421, 111) = 421x + 111y
.
Solution:
We have a = 421
and b = 111
.
We work backwards from the penultimate line of the Euclidean Algorithm, as follows.
1 = 4 - 1 x 3 | (start with penultimate line (6), rearranged with 1 on the left and lower factor, 3, on the right) |
1 = 4 - 1 x (19 - 4 x 4) | (substitute for lower factor, 3, from line (5)) |
1 = -1 x 19 + 5 x 4 | (rearrange for new lower factor, 4) |
1 = -1 x 19 + 5 x (23 - 1 x 19) | (substitute for lower factor, 4, from line (4)) |
1 = 5 x 23 - 6 x 19 | (shift higher factor to left) |
1 = 5 x 23 - 6 x (88 - 3 x 23) | (expand lower factor, 19, from line (3)) |
1 = -6 x 88 + 23 x 23 | (rearrange to put new lowest factor, 23, on the right) |
1 = -6 x 88 + 23 x (111 - 1 x 88) | |
1 = 23 x 111 - 29 x 88 | (always keep coefficients to the left of the factors) |
1 = 23 x 111 - 29 x (421 - 3 x 111) | |
1 = -29 x 421 + 110 x 111 | (finally, check there is always one negative coefficient) |
Hence we obtain x = -29
and y = 110
.
Note that we always do things in two steps on two separate lines:
- rearrange the equation to put the lower factor on the right, and
- substitute for the lower factor using the line above in the original Euclidean algorithm solution.
Finally, we end up with what we've been asked to find, an expression of the form d = 421x + 111y
.
Be strict and don't take shortcuts, especially under exam conditions. Always do both steps on separate lines and keep the lines ordered
in the form
d = coefft x higher_factor + coefft x lower_factor
or
d = coefft x higher_factor + coefft x (expanded_lower_factor)
.
(Note we swap the order from part (a) to keep the factors on the right).
Note also that you don't need to multiply out the
coefft x (expanded_lower_factor)
terms in full; it just requires simple arithmetic to add or subtract the coefficients.
So, for example, in line 4 above, the coefficient of the 19 term is -1 + 5 x (-1) = -6
. This is why we keep the factors
on the right.
When you've finished, you must always have one positive and one negative result for x and y. Then you can always check that your solution works (this takes seconds to do even under exam conditions)
xa + yb = -29 x 421 + 110 x 111 = -12209 + 12210 = 1, as required
If this doesn't work, check that the arithmetic on each rearranged line holds. One line must be wrong, so you'll soon find the error.
Another example
Question 2(b): Determine a solution to the linear Diophantine equation gcd(93, 219) = 219x + 93y
.
Solution:
We have from part (a) that gcd(93, 219) = 3
. We work backwards from the penultimate line of the Euclidean Algorithm, as follows.
3 = 27 - 4 x 6 = 27 - 4 x (33 - 27 x 1) = -4 x 33 + 5 x 27 = -4 x 33 + 5 x (93 - 2 x 33) = 5 x 93 - 14 x 33 = 5 x 93 - 14 x (219 - 2 x 93) = -14 x 219 + 33 x 93
Therefore a solution to gcd(93, 219) = 219x + 93y
is
x = -14
and y = 33
.
Check: 219x + 93y = 219 x (-14) + 93 x 33 = -3066 + 3069 = 3
, as required.
Finding the modular inverse
The modular inverse of an integer e modulo n
is defined as the value of d such that ed = 1 mod n
.
We write d = (1/e) mod n
or d = e^{-1} mod n
.
The inverse exists if and only if gcd(n,e)=1
.
To find this value for large numbers on a computer, we use the extended Euclidean algorithm, but there are simpler methods for smaller numbers.
Trial and error
For very small numbers we can use trial and error. For example, to find the inverse of 3 modulo 20,
we have e=3
and n=20
and we need to find the integer
d such that when ed is divided by 20, the remainder is 1.
Try d=1, ed=3x1=3, 3 divided by 20 is 0 remainder 3, so no good Try d=2, ed=3x2=6, 6 divided by 20 is 0 remainder 6, so no good ... Try d=6, ed=3x6=18, 18 divided by 20 is 0 remainder 18, so no good Try d=7, ed=3x7=21, 21 divided by 20 is 1 remainder 1 => HOORAY.
So d=7
satisfies the relationship. Therefore a modular inverse
d = 3^{-1} mod 20 = 7
.
Note also that there are other, larger values of d that work, too.
d = 7 + 1 x 20 = 27 will work since 27 x 3 = 81 = 3 x 20 + 1 d = 7 + 2 x 20 = 47 will work since 47 x 3 = 141 = 7 x 20 + 1 d = 7 + 3 x 20 = 67 will work since 67 x 3 = 201 = 10 x 20 + 1 ... etc.
There are negative inverses as well, d = -13, -33, -53, ...
d = 7 - 1 x 20 = -13 will work since -13 x 3 = -39 = -2 x 20 + 1 d = 7 - 2 x 20 = -33 will work since -33 x 3 = -99 = -5 x 20 + 1 ... etc.
This is an issue when discussing the value of phi in the RSA algorithm, but the usual convention is to use the least positive residue between 0 and n-1.
Try successive powers
An alternative quick method to find e^{-1} mod n
for small integers is to compute the values of
e^{2}, e^{3}, e^{4}, ... (mod n) until the result is one
(this will always happen before you get to e^{n}, often much sooner).
If k > 0 is an integer for which e^{k} ≡ 1, then the inverse of e is the value of e^{k-1}.
This follows because e^{k} = e.e^{k-1} ≡ 1, and so, by definition, e^{k-1} is the inverse of e.
For example, working modulo 20 for e = 3 we have
e^{1} = 3, e^{2} = 9, e^{3} = 27 ≡
7, e^{4} = 7 x 3 = 21 ≡ 1
.
So e^{4} ≡ 1 and therefore the value of e^{3} ≡ 7 is the inverse.
That is, 3^{-1} ≡ 7 mod 20
.
For another example, to find 2^{-1} mod 17
, we compute
2^{1} = 2, 2^{2} = 4, 2^{3} = 8, 2^{4} = 16, 2^{5} = 32 ≡ 15,
2^{6} = 30 ≡ 13, 2^{7} = 26 ≡ 9, 2^{8} = 18 ≡ 1 (mod 17)
.
Hence 2^{-1} ≡ 9 mod 17
.
Check: 2 x 9 = 18 = 1 x 17 + 1 ≡ 1 (mod 17).
Using the Euclidean algorithm
If we need to find d = e^{-1} mod n
and we can find integers
x and y such that
ex + ny = 1
then the inverse d is the value of x. (Can't figure this? See below).
Does this look familiar? It's the very expression we derived above.
Using our method above to find d = 3^{-1} mod 20
, we first obtain gcd(20, 3)
and check that it's
one (otherwise the inverse doesn't exist).
20 = 3 x 6 + 2 3 = 2 x 1 + 1
giving gcd(20, 3) = 1
. Then we use the numbers in this calculation to find Bezout's identity
nx + ey = 1
,
1 = 3 - 1 x 2 = 3 - 1 x (20 - 6 x 3) = -1 x 20 + 7 x 3
The value of x (the coefficent of 3) is 7, so the inverse is 7.
Similarly, to find the inverse of 111 modulo 421, we can use the expression we derived above
110 x 111 - 29 x 421 = 1
and this gives x = 110
, so the inverse
111^{-1} mod 421 = 110
.
Check: 111 x 110 = 12210 = 29 x 421 + 1 ≡ 1 (mod 421)
Question: what is the value of 93^{-1} mod 219
?
Hint: see question 2(b) above.
Bigger hint: the answer is not 33 (or -14 or 205).
If the algorithm gives you a negative value for the inverse, just add the modulus to the result.
Remember that 3d ≡ 1 (mod 20)
is satisfied by
7 + 20k
for any integer k, positive or negative.
So not only are 7,27,47,67,...
valid inverses, but so are -13,-33,-53,...
.
If the method above gives you -13
, add the modulus to get -13 + 20 = 7
.
See the code below for Computing the modular inverse, which uses only non-negative integers.
For a command-line program to compute the modular inverse for very large integers, try the bd_ModInv
program in our Modular Arithmetic Freeware software.
This uses our free open-source BigDigits code.
Why does finding the integer combination ex + ny = 1 gives us the inverse of e modulo n?
For any integer y we have ex + ny ≡ ex (mod n)
because n always divides ny and so ny ≡ 0 (mod n)
.
Hence ex ≡ 1 (mod n)
and by definition this means that x is the inverse of e.
Python Code to find modular inverse
1 def mod_inverse(u, v): 2 """Compute the modular inverse of `u` modulo `v` 3 (or None if does not exist).""" 4 if gcd(u, v) != 1: 5 return None 6 u1, u2, u3 = 1, 0, u 7 v1, v2, v3 = 0, 1, v 8 while v3 != 0: 9 q = u3 // v3 10 v1, v2, v3, u1, u2, u3 = (u1 - q * v1), (u2 - q * v2), (u3 - q * v3), v1, v2, v3 11 return u1 % v 12 13 print(mod_inverse(3, 20)) # 7
The Extended Euclidean Algorithm
The Extended Euclidean Algorithm is just a fancier way of doing what we did
Using the Euclidean algorithm
above.
It involves using extra variables to compute
ax + by = gcd(a, b)
as we go through the Euclidean algorithm in a single pass.
It's more efficient to use in a computer program.
But if you are doing a calculation by hand, honestly, it's simpler just to use the method above.
Algorithm: Extended Euclidean algorithm. (Ref: [MENE97], Algorithm 2.107)
INPUT: Two non-negative integers a and b with
a ≥ b
.OUTPUT:
d = gcd(a, b)
and integers x and y satifying ax + by = d
.- If
b = 0
then setd = a, x = 1, y = 0
, and return(d, x, y). - Set x_{2} = 1, x_{1} = 0, y_{2} = 0, y_{1} = 1
- While
b > 0
, do- q = floor(a/b), r = a - qb, x = x_{2} - qx_{1}, y = y_{2} - q y_{1}.
- a = b, b = r, x_{2} = x_{1}, x_{1} = x, y_{2} = y_{1}, y_{1} = y.
- Set d = a, x = x_{2}, y = y_{2}, and return(d, x, y).
There are more efficient methods to do both the Euclidean algorithm and the extended Euclidean algorithm on a computer using binary techniques. See [MENE97] algorithms 14.54 and 14.61, and the Binary GCD code below.
Computer programs
Using the Euclidean Algorithm to find the gcd
int gcd(int a, int b)
{
int r;
if (a < 0) a = -a;
if (b < 0) b = -b;
if (b > a) { /* swap */
r = b; b = a; a = r;
}
while (b > 0) {
r = a % b;
a = b;
b = r;
}
return a;
}
Binary GCD
2011-11-17. The following code is a blend of Cohen's algorithm 1.3.5 [COHE96, p.14] and Menezes' algorithm 14.54 [MENE97, p.606] to find the GCD using the binary algorithm. Note that it only uses shifts to multiply or divide by a power of 2 and so avoids doing expensive multiplication and division operations, which matters when you are dealing with large multiple-precision numbers.
Well, apart from the first modulo reduction in step 1, which is a worthwhile one-off expense to make sure we always work on the smallest of a and b, and immediately catches the common case where b divides a.
#define ISODD(x) ((x) & 0x1) #define ISEVEN(x) (!ISODD(x)) unsigned int gcd_binary(unsigned int a, unsigned int b) { /* Returns gcd(a, b) */ unsigned int r, t, k; /* 1. [Reduce size once] */ if (a < b) { /* Exchange a and b */ t = a; a = b; b = t; } /* If b = 0 output a and stop */ if (0 == b) { return a; } /* Set r <-- a mod b, a <-- b, b <-- r */ r = a % b; a = b; b = r; /* If b = 0 output a and stop */ if (0 == b) { return a; } /* 2. [Compute power of 2] */ k = 0; /* g = 2^k <-- 1 */ while (ISEVEN(a) && ISEVEN(b)) { /* While a and b are even */ a >>= 1; /* a <-- a/2 */ b >>= 1; /* b <-- b/2 */ k++; /* g <-- 2g */ } while (a != 0) { /* 3. [Remove initial powers of 2] */ while (ISEVEN(a)) { a >>= 1; /* a <-- a/2 until a is odd */ } while (ISEVEN(b)) { b >>= 1; /* b <-- b/2 until b is odd */ } /* 4. [Subtract and halve] t <-- |a - b|/2 */ if (b > a) t = (b - a) >> 1; else t = (a - b) >> 1; /* If a >= b then a <-- t, otherwise b <-- t */ if (a >= b) a = t; else b = t; /* 5. [Loop until a = 0] */ } /* Output (2^k.b) and stop */ return (b << k); }
Extended Euclidean Algorithm
See Pate Williams' implementation of Menezes' algorithm 2.107 exteuc.c. The key parts of his code are
void extended_euclid(long a, long b, long *x,
long *y, long *d)
/* calculates a * *x + b * *y = gcd(a, b) = *d */
/* Author: Pate Williams (c) 1997 */
{
long q, r, x1, x2, y1, y2;
if (b == 0) {
*d = a, *x = 1, *y = 0;
return;
}
x2 = 1, x1 = 0, y2 = 0, y1 = 1;
while (b > 0) {
q = a / b, r = a - q * b;
*x = x2 - q * x1, *y = y2 - q * y1;
a = b, b = r;
x2 = x1, x1 = *x, y2 = y1, y1 = *y;
}
*d = a, *x = x2, *y = y2;
}
The output from the full program with input a = 4864, b = 3458 is
------------------------------------------------- q r x y a b x2 x1 y2 y1 ------------------------------------------------- 1 1406 1 -1 3458 1406 0 1 1 -1 2 646 -2 3 1406 646 1 -2 -1 3 2 114 5 -7 646 114 -2 5 3 -7 5 76 -27 38 114 76 5 -27 -7 38 1 38 32 -45 76 38 -27 32 38 -45 2 0 -91 128 38 0 32 -91 -45 128 ------------------------------------------------- x = 32 y = -45 d = 38
That is, gcd(4864, 3458) = 38
and 32 x 4864 - 45 x 3458 = 38
.
Computing the modular inverse
This code is an adaptation of the extended Euclidean algorithm from Knuth
[KNU298, Vol 2 Algorithm X p 342] avoiding negative integers.
It computes the multiplicative inverse of u modulo v,
u^{-1} (mod v)
, and returns either the inverse as a positive integer less than v,
or zero if no inverse exists.
unsigned int modinv(unsigned int u, unsigned int v) { unsigned int inv, u1, u3, v1, v3, t1, t3, q; int iter; /* Step X1. Initialise */ u1 = 1; u3 = u; v1 = 0; v3 = v; /* Remember odd/even iterations */ iter = 1; /* Step X2. Loop while v3 != 0 */ while (v3 != 0) { /* Step X3. Divide and "Subtract" */ q = u3 / v3; t3 = u3 % v3; t1 = u1 + q * v1; /* Swap */ u1 = v1; v1 = t1; u3 = v3; v3 = t3; iter = -iter; } /* Make sure u3 = gcd(u,v) == 1 */ if (u3 != 1) return 0; /* Error: No inverse exists */ /* Ensure a positive result */ if (iter < 0) inv = v - u1; else inv = u1; return inv; }
References
- [COHE96] Henri Cohen, A Course in Computational Algebraic Number Theory, Springer, 1996.
- [JONE98] Jones, Gareth A. and J. Mary Jones, Elementary Number Theory, Springer-Verlag, 1998.
- [KNU298] Donald E. Knuth, The Art of Computer Programming, Volume 2: Seminumerical Algorithms, 3rd ed., Addison-Wesley, 1998.
- [MENE97] Menezes, van Oorschot and Vanstone, Handbook of Applied Cryptography, CRC Press LLC, 1997. The complete book is available on-line.
Contact us
To comment on this page or ask a question, please send us a message.
This page first published 14 August 2010 and last updated 2 June 2023
Comments
8 comments so far
[Comments are now closed]