patternMajor
What is most efficient for GCD?
Viewed 0 times
whatefficientforgcdmost
Problem
I know that Euclid’s algorithm is the best algorithm for getting the GCD (great common divisor) of a list of positive integers.
But in practice you can code this algorithm in various ways. (In my case, I decided to use Java, but C/C++ may be another option).
I need to use the most efficient code possible in my program.
In recursive mode, you can write:
And in iterative mode, it looks like this:
There is also the Binary algorithm for the GCD, which may be coded simply like this:
But in practice you can code this algorithm in various ways. (In my case, I decided to use Java, but C/C++ may be another option).
I need to use the most efficient code possible in my program.
In recursive mode, you can write:
static long gcd (long a, long b){
a = Math.abs(a); b = Math.abs(b);
return (b==0) ? a : gcd(b, a%b);
}And in iterative mode, it looks like this:
static long gcd (long a, long b) {
long r, i;
while(b!=0){
r = a % b;
a = b;
b = r;
}
return a;
}There is also the Binary algorithm for the GCD, which may be coded simply like this:
int gcd (int a, int b)
{
while(b) b ^= a ^= b ^= a %= b;
return a;
}Solution
Your two algorithms are equivalent (at least for positive integers, what happens with negative integers in the imperative version depends on Java's semantics for
$$\begin{gather*}
a_{i+1} = b_i \\
b_{i+1} = a_i \mathbin{\mathrm{mod}} b_i \\
\end{gather*}$$
In the imperative version, let $a'_i$ and $b'_i$ be the values of the variables
$$\begin{gather*}
a'_{i+1} = b'_i \\
b'_{i+1} = a'_i \mathbin{\mathrm{mod}} b'_i \\
\end{gather*}$$
Notice a resemblance? Your imperative version and your recursive version are calculating exactly the same values. Furthermore, they both end at the same time, when $a_i=0$ (resp. $a'_i=0$), so they perform the same number of iterations. So algorithmically speaking, there is no difference between the two. Any difference will be a matter of implementation, highly dependent on the compiler, the hardware it runs on, and quite possibly the operating system and what other programs are running concurrently.
The recursive version makes only tail recursive calls. Most compilers for imperative languages do not optimize these, and so it is likely that the code they generate will waste a little time and memory constructing a stack frame at each iteration. With a compiler that optimizes tail calls (compilers for functional languages almost always do), the generated machine code may well be the same for both (assuming you harmonize those calls to
% which I don't know by heart). In the recursive version, let $a_i$ and $b_i$ be the argument of the $i$th recursive call:$$\begin{gather*}
a_{i+1} = b_i \\
b_{i+1} = a_i \mathbin{\mathrm{mod}} b_i \\
\end{gather*}$$
In the imperative version, let $a'_i$ and $b'_i$ be the values of the variables
a and b at the beginning of the $i$th iteration of the loop.$$\begin{gather*}
a'_{i+1} = b'_i \\
b'_{i+1} = a'_i \mathbin{\mathrm{mod}} b'_i \\
\end{gather*}$$
Notice a resemblance? Your imperative version and your recursive version are calculating exactly the same values. Furthermore, they both end at the same time, when $a_i=0$ (resp. $a'_i=0$), so they perform the same number of iterations. So algorithmically speaking, there is no difference between the two. Any difference will be a matter of implementation, highly dependent on the compiler, the hardware it runs on, and quite possibly the operating system and what other programs are running concurrently.
The recursive version makes only tail recursive calls. Most compilers for imperative languages do not optimize these, and so it is likely that the code they generate will waste a little time and memory constructing a stack frame at each iteration. With a compiler that optimizes tail calls (compilers for functional languages almost always do), the generated machine code may well be the same for both (assuming you harmonize those calls to
abs).Context
StackExchange Computer Science Q#1447, answer score: 26
Revisions (0)
No revisions yet.