skip to content

In Euclid's algorithm, why does replacing (a, b) with (b, a mod b) leave the gcd unchanged?

level: juniorimportance: must knowfreq 78%

answer

  1. Think about divisors, not about the numbers
  2. Write a as q times b plus r
  3. Anything dividing a and b divides r
  4. Now argue the reverse direction too
  5. Identical divisor sets, identical maximum

basics

~20 s

Every common divisor of a and b also divides a mod b, and every common divisor of b and a mod b also divides a. The two pairs therefore have exactly the same common divisors, and so the same greatest one.

solid answer

~50 s

Write `a = q*b + r`, where `r = a mod b`. If some number `d` divides both `a` and `b`, then it divides `r = a - q*b`, so it is a common divisor of `b` and `r`. Going the other way, if `d` divides `b` and `r`, it divides `q*b + r = a`. The two pairs share an identical set of common divisors, so the largest one is identical too — `gcd(a, b) = gcd(b, a mod b)`. That is the invariant the loop rides on. It terminates because the remainders are non-negative and strictly shrinking, so `b` must reach 0, and at that point the answer is sitting in `a`, since `gcd(a, 0) = a`. Reducing 1920 by 1080 this way lands on gcd 120, which turns an image size into the ratio 16:9.

code

pseudocode · 7 lines
pseudocode
// a >= 0, b >= 0, not both zero
while b != 0:
    r = a mod b        // 0 <= r < b
    a = b
    b = r
// b == 0 here, and gcd(a, 0) == a
return a

go deeper

for a junior

Recall the step (a, b) -> (b, a mod b), the stopping condition b == 0, and that the answer is then the first value. Be able to run it by hand on a two-number example without hesitating.

for a middle

Explain the invariant in both directions: any common divisor of the pair divides the remainder, and any common divisor of the remainder and the divisor divides the original. Then state why the remainders force termination.

for a senior

Show where this lands in real work — normalising ratios and dividing out totals — and note the guards that matter: both inputs zero, negative inputs, and the fact that the quotients after dividing by the gcd are coprime by construction.

for a principal

Frame it as choosing an exact integer routine over floating-point ratio arithmetic, and be ready to say when a hand-written gcd is worth owning versus leaning on a well-tested arithmetic utility the team already maintains.

## What the algorithm actually does The greatest common divisor of two non-negative integers, not both zero, is the largest integer dividing both of them. Euclid's algorithm computes it by repeatedly replacing the pair `(a, b)` with `(b, a mod b)` until the second element is 0: ``` while b != 0: r = a mod b a = b b = r return a ``` On a thumbnail service reducing an image size of 1920 by 1080 to its ratio, the pairs run `(1920, 1080) -> (1080, 840) -> (840, 240) -> (240, 120) -> (120, 0)`, so the gcd is 120, and dividing both dimensions by it gives 16 and 9. ## The invariant, proved both directions The whole correctness argument is one sentence about **divisor sets**, not about the numbers themselves. Division with remainder gives `a = q*b + r` with `0 <= r < b`. - Suppose `d` divides `a` and `d` divides `b`. Then `d` divides `a - q*b`, which is exactly `r`. So `d` is a common divisor of `(b, r)`. - Suppose `d` divides `b` and `d` divides `r`. Then `d` divides `q*b + r`, which is exactly `a`. So `d` is a common divisor of `(a, b)`. The implication runs both ways, so the two pairs have the *same set* of common divisors — not merely overlapping sets, not merely the same maximum by coincidence. Identical sets have identical maxima, which is why the step is safe to repeat forever. This is the point candidates most often fumble: they assert the gcd is preserved because "the remainder still contains the common factors", which is only half the argument. An interviewer who pushes back with "prove nothing was lost" is asking for the second direction. ## Why the loop ends, and what it ends holding Each new second element is a remainder, so it is strictly smaller than the previous second element and never negative. A strictly decreasing sequence of non-negative integers cannot run forever, so `b` reaches 0 in a finite number of steps. The base case is the identity `gcd(a, 0) = a`: every integer divides 0, so the common divisors of `a` and 0 are just the divisors of `a`, the largest of which is `a` itself. That identity is also what makes 0 the natural starting accumulator when you fold gcd across many numbers. A related detail worth knowing: the loop needs no explicit sorting step. If you call it with the smaller number first, the very first iteration computes `a mod b = a`, and the assignment swaps the pair — one wasted iteration and then it proceeds normally. ## Reduction to lowest terms and coprimality Dividing both inputs by their gcd is exactly the operation that reduces a ratio to lowest terms, and the result is always **coprime**: `gcd(a/g, b/g) = 1` where `g = gcd(a, b)`. If it were not 1, some `k > 1` would divide both quotients, and then `k*g` would be a common divisor of `a` and `b` bigger than `g`, contradicting `g` being greatest. Coprime does **not** mean either number is prime — 16 and 9 are coprime and neither is prime. It only means they share no prime factor. This is why one gcd call, rather than a loop peeling off common factors one at a time, is the right way to normalise a ratio: the gcd is the total common factor, so a single division finishes the job. ## Common ways this goes wrong Using a subtraction step instead of a remainder step is still correct — `gcd(a, b) = gcd(a - b, b)` for `a > b` by the same divisor-set argument — but it can take an enormous number of iterations when one number dwarfs the other. Writing the swap in the wrong order (`a = r; b = a` after clobbering `a`) either loops forever or returns nonsense, which is why the temporary `r` matters. And calling gcd on two zeros has no meaningful answer; the usual convention is to define `gcd(0, 0) = 0` and to guard against it before dividing by the result.

  • Why is the loop guaranteed to stop?
    Each iteration puts a remainder in the second slot, and a remainder is strictly smaller than the divisor it came from and never negative. A strictly decreasing sequence of non-negative integers has to hit 0 in finitely many steps, and once the second value is 0 the first holds the answer, because gcd(a, 0) = a.
  • After dividing both numbers by their gcd, what is the gcd of the two results?
    Always 1 — the results are coprime. If some k > 1 divided both quotients, then k times the original gcd would be a common divisor of the original pair and larger than the gcd, which contradicts it being greatest. That is exactly why one gcd division reduces a ratio fully, with no leftover common factor to strip.
  • Does the algorithm still work if you pass the smaller number first?
    Yes. If a < b, then a mod b is just a, so the first iteration assigns (b, a) and effectively performs the swap for you. It costs one extra iteration and nothing else, so an explicit ordering step is optional rather than required for correctness.

Swapping a tall stack of coins for the leftover after making equal piles: which coin values divide both stacks evenly never changes, so the leftover is a smaller problem with the same answer.

saying these in an interview costs you the question

  • Argues only that the remainder keeps the common factors, never the reverse
  • Says coprime means both numbers are prime
  • Claims gcd(a, 0) is 0 rather than a
  • Thinks the inputs must be sorted or the algorithm breaks
  • Peels common factors off one at a time instead of dividing by the gcd

context