Extended Euclidean Algorithm¶
While the Euclidean algorithm calculates only the greatest common divisor (GCD) of two integers
It's important to note that by Bézout's identity we can always find such a representation. For instance,
A more general form of that problem is discussed in the article about Linear Diophantine Equations. It will build upon this algorithm.
Algorithm¶
We will denote the GCD of
The changes to the original algorithm are very simple.
If we recall the algorithm, we can see that the algorithm ends with
Starting from these coefficients
Let us assume we found the coefficients
and we want to find the pair
We can represent
Substituting this expression in the coefficient equation of
and after rearranging the terms:
We found the values of
Implementation¶
int gcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1;
int d = gcd(b, a % b, x1, y1);
x = y1;
y = x1 - y1 * (a / b);
return d;
}
The recursive function above returns the GCD and the values of coefficients to x
and y
(which are passed by reference to the function).
This implementation of extended Euclidean algorithm produces correct results for negative integers as well.
Iterative version¶
It's also possible to write the Extended Euclidean algorithm in an iterative way. Because it avoids recursion, the code will run a little bit faster than the recursive one.
int gcd(int a, int b, int& x, int& y) {
x = 1, y = 0;
int x1 = 0, y1 = 1, a1 = a, b1 = b;
while (b1) {
int q = a1 / b1;
tie(x, x1) = make_tuple(x1, x - q * x1);
tie(y, y1) = make_tuple(y1, y - q * y1);
tie(a1, b1) = make_tuple(b1, a1 - q * b1);
}
return a1;
}
If you look closely at the variables a1
and b1
, you can notice that they take exactly the same values as in the iterative version of the normal Euclidean algorithm. So the algorithm will at least compute the correct GCD.
To see why the algorithm computes the correct coefficients, consider that the following invariants hold at any given time (before the while loop begins and at the end of each iteration):
Let the values at the end of an iteration be denoted by a prime (
For the first invariant to hold, the following should be true:
Similarly for the second invariant, the following should hold:
By comparing the coefficients of
At the end we know that
You can even optimize the code more, and remove the variable