Volume 3: Discrete and Probabilistic Mathematics · Part VI: Discrete Mathematics

Chapter 23. Integers, Divisibility, and Modular Arithmetic

Chapter map: we go back to the whole numbers and ask questions that ordinary arithmetic skips. When does one number divide another? What are the indivisible building blocks? How do you find the largest common divisor of two 300-digit numbers without factoring them? Then we wrap the number line into a circle. That "clock arithmetic" turns out to be the arithmetic your CPU already does. It is also the arithmetic behind hash tables, check digits, random-number generators, and the public-key cryptography that protects nearly every web connection you make. The chapter ends by running RSA by hand, with nothing hidden.

Where this chapter sits

Prerequisites: whole numbers, integers, and the order of operations (Chapter 1); factors, multiples and common denominators (Chapter 2); exponents and their laws (Chapter 3); using letters for numbers (Chapter 4). No algebra beyond that is assumed. The occasional "proof" here is short and informal. Chapter 22 treats proof technique in its own right, and you can read the two chapters in either order.

Unlocks: counting arguments in Chapter 24; randomness and simulation in Chapter 29; and every later mention of hashing, checksums, or cryptography. Modular arithmetic also gives you a useful way to look at the overflow behaviour of fixed-width integers, which Chapter 32 picks up again.

Number theory has a reputation as the "purest" corner of mathematics. G. H. Hardy boasted in 1940 that it had no practical use whatsoever. Thirty-seven years later RSA made it one of the most practically important subjects there is. Keep that irony in mind. Everything in this chapter is elementary, meaning it needs nothing past arithmetic, but none of it is trivial.

23.1. Divisibility and the division algorithm

23.1.1. The problem

You have 1,071 identical tiles and want to lay them in a complete rectangle with no gaps and none left over. Which rectangle shapes work? You have 7 days of logs and want them bucketed by weekday: which bucket does day 1,000 fall in? A loop has to process items in batches of 64. How many full batches are there, and how many items are left over?

All three questions ask the same thing: what happens when one whole number is divided by another and we refuse to leave the integers. There are no fractions and no decimals. There is a whole-number quotient and a whole-number remainder.

23.1.2. Intuition

Think of dividing 23 by 5 as dealing 23 cards into piles of 5. You make 4 complete piles and 3 cards are left over:

\[23 = 4 \cdot 5 + 3.\]

The leftover is always smaller than the pile size. If it weren’t, you could make one more pile. That simple fact is what everything in this chapter rests on.

23.1.3. Vocabulary and notation

Dividend, divisor, quotient, remainder

In \(23 = 4 \cdot 5 + 3\) the number being divided (23) is the dividend. The number you divide by (5) is the divisor. The number of whole times it fits (4) is the quotient, and what is left (3) is the remainder. "Quotient" comes from the Latin quotiens, "how many times".

Divides, factor, multiple

For integers \(a\) and \(b\), we say \(a\) divides \(b\), written \(a \mid b\), if \(b = ka\) for some integer \(k\). Equivalently, dividing \(b\) by \(a\) leaves remainder 0. Then \(a\) is a divisor (or factor) of \(b\), and \(b\) is a multiple of \(a\).

So \(3 \mid 12\) because \(12 = 4 \cdot 3\), and \(5 \nmid 12\) ("5 does not divide 12"). The vertical bar is a statement (true or false), not an operation: \(3 \mid 12\) is not the number 4. Don’t confuse it with the fraction \(3/12\).

Even and odd, parity

An integer is even if \(2 \mid n\) and odd otherwise. Whether a number is even or odd is its parity. Every odd number can be written as \(2k + 1\) for some integer \(k\).

23.1.4. The division algorithm

The card-dealing picture becomes a theorem. (The name is old. It is a statement that a quotient and remainder exist, not a step-by-step algorithm.)

Division algorithm (quotient–remainder theorem)

For any integer \(a\) and any positive integer \(b\), there are unique integers \(q\) (the quotient) and \(r\) (the remainder) with

\[a = qb + r, \qquad 0 \le r < b.\]

We write \(r = a \bmod b\), read "\(a\) mod \(b\)".

The condition \(0 \le r < b\) is what makes the answer unique. Without it, \(23 = 3 \cdot 5 + 8\) would also be a valid split. With it, there is only one choice: take \(q\) to be the largest integer with \(qb \le a\). That works for negative \(a\) too:

\[-23 = (-5)\cdot 5 + 2, \qquad\text{so } -23 \bmod 5 = 2.\]

Note that the quotient is \(-5\), not \(-4\). Since \((-4)\cdot 5 = -20\), that choice would give remainder \(-3\), which breaks \(0 \le r\). Programming languages disagree about this case. Section 23.7 sorts out who does what.

23.1.5. Why divisibility behaves nicely

Three facts follow directly from the definition. Each one is a one-line argument, so here they are:

  1. If \(d \mid a\) and \(d \mid b\), then \(d \mid (a + b)\) and \(d \mid (a - b)\). Write \(a = kd\) and \(b = ld\). Then \(a \pm b = (k \pm l)d\).

  2. If \(d \mid a\), then \(d \mid ca\) for every integer \(c\). \(ca = (ck)d\).

  3. Divisibility is transitive: if \(a \mid b\) and \(b \mid c\), then \(a \mid c\). \(c = mb = m(ka) = (mk)a\).

Combining the first two: if \(d\) divides both \(a\) and \(b\), then \(d\) divides every integer combination \(xa + yb\). We’ll lean on this sentence repeatedly. It is the engine behind both the Euclidean algorithm and Bézout’s identity.

23.1.6. Worked example: tiles and weekdays

Which rectangles can 1,071 tiles make? A rectangle with sides \(w \times h\) uses \(wh\) tiles, so we need the divisors of 1,071. Divide by small numbers:

\[\begin{aligned} 1071 &= 3 \cdot 357 &&\text{(digit sum } 1+0+7+1 = 9 \text{ is divisible by 3)}\\ 357 &= 3 \cdot 119 &&\text{(digit sum } 15\text{)}\\ 119 &= 7 \cdot 17 &&\\ \text{so } 1071 &= 3^2 \cdot 7 \cdot 17. \end{aligned}\]

Each divisor picks 0, 1 or 2 threes, 0 or 1 seven, and 0 or 1 seventeen, so there are \(3 \cdot 2 \cdot 2 = 12\) divisors: 1, 3, 7, 9, 17, 21, 51, 63, 119, 153, 357, 1071. That gives six rectangle shapes up to rotation: \(1\times1071\), \(3\times357\), \(7\times153\), \(9\times119\), \(17\times63\) and \(21\times51\).

Day 1,000. If day 0 is a Monday, then day 1,000 lands on weekday \(1000 \bmod 7\):

\[1000 = 142 \cdot 7 + 6 \quad\Rightarrow\quad 1000 \bmod 7 = 6,\]

six days after Monday, a Sunday.

Divisibility tests are modular arithmetic in disguise

The schoolroom test "a number is divisible by 3 (or 9) exactly when its digit sum is" isn’t a coincidence. We’ll prove it in two lines in Section 23.6, along with the stranger test for 11: alternate the signs of the digits. For 1,071 that gives \(1 - 7 + 0 - 1 = -7\), which is not a multiple of 11, so 11 does not divide 1,071.

US curriculum

Factors, multiples, and divisibility rules come in grades 4–6 (Common Core 4.OA.B.4: "find all factor pairs for a whole number in the range 1–100"). Remainders appear with long division in grades 4–5. The formal division algorithm and the \(a \mid b\) notation usually wait until a college Discrete Mathematics course or a competition-math class (MATHCOUNTS, AMC).

23.2. Primes and the fundamental theorem of arithmetic

23.2.1. The problem

Some numbers break into smaller factors: \(1071 = 3^2 \cdot 7 \cdot 17\). Some don’t: 17 has no divisors except 1 and itself. Is there a finite list of these "atoms", or do they go on forever? And when you break a number into atoms, can two different people end up with two different answers?

23.2.2. Vocabulary

Prime, composite, unit

A prime is an integer \(p > 1\) whose only positive divisors are 1 and \(p\). An integer \(n > 1\) that is not prime is composite: it can be written \(n = ab\) with \(1 < a, b < n\). The number 1 is neither. It is called a unit.

The primes start 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, …​ and 2 is the only even one.

Prime factorization

A prime factorization writes a number as a product of primes, usually grouped with exponents in increasing order: \(360 = 2^3 \cdot 3^2 \cdot 5\). The exponent of \(p\) is called the multiplicity of \(p\).

Why isn’t 1 prime?

If 1 counted as prime, factorizations would stop being unique: \(6 = 2 \cdot 3 = 1 \cdot 2 \cdot 3 = 1 \cdot 1 \cdot 2 \cdot 3 = \cdots\). Mathematicians chose to exclude 1 so that the theorem below could be stated cleanly. Definitions are design decisions, just as they are in an API.

23.2.3. The fundamental theorem of arithmetic

Fundamental theorem of arithmetic

Every integer \(n > 1\) can be written as a product of primes, and this factorization is unique apart from the order of the factors.

It has two halves, and they deserve different amounts of attention.

Existence is the easy half. Take \(n\). If it is prime, you’re done. If not, split it as \(n = ab\) with both factors smaller, and keep splitting. The numbers shrink every time, so the process must stop, and when it stops every piece is prime. If you sketch the splits you get a factor tree:

\[360 \to 36 \cdot 10 \to (6 \cdot 6)(2 \cdot 5) \to (2\cdot 3)(2 \cdot 3)(2 \cdot 5) = 2^3 \cdot 3^2 \cdot 5.\]

Uniqueness is the deep half. If you’d started with \(360 = 8 \cdot 45\), could you have finished with different primes? The answer is no, but the reason needs a fact we don’t have yet, Euclid’s lemma (if a prime divides a product, it divides one of the factors). We’ll prove that lemma in Section 23.5 using the Euclidean algorithm. Uniqueness then follows quickly. Two factorizations of the same number share any prime \(p\) that appears in the first, because \(p\) divides the product on the second side and so must divide (that is, equal) one of its primes. Cancel it from both sides and repeat.

Uniqueness can fail

Uniqueness isn’t automatic. In the number system made of all \(a + b\sqrt{-5}\) with integer \(a, b\), the number 6 has two genuinely different factorizations into "atoms": \(6 = 2 \cdot 3 = (1 + \sqrt{-5})(1 - \sqrt{-5})\). In the 1840s, mathematicians attacking Fermat’s Last Theorem had assumed unique factorization in systems like this one. When Kummer noticed it can fail there, the repair led to much of modern algebra.

23.2.4. Finding a factorization: trial division

To factor \(n\), try dividing by 2, 3, 4, 5, …​ in turn. Whenever a trial divisor \(d\) works, divide it out as many times as it goes and carry on with what’s left. Two observations make this efficient enough for small numbers.

  • You only need to try \(d\) up to \(\sqrt{n}\). If \(n = ab\) with \(a \le b\), then \(a \cdot a \le ab = n\), so \(a \le \sqrt{n}\). Any composite number has a factor no larger than its square root. If nothing up to \(\sqrt{n}\) divides \(n\), then \(n\) is prime.

  • Composite trial divisors never succeed, because their prime factors were already divided out. Trying 4 after removing every 2 is wasted work but harmless.

Example 120. Procedure — Prime factorization by trial division

Input: an integer \(n > 1\).

Steps:

  1. Set \(d = 2\) and start with an empty list of factors.

  2. While \(d \cdot d \le n\):

    1. While \(d \mid n\): record \(d\) as a factor and replace \(n\) by \(n / d\).

    2. Increase \(d\) by 1.

  3. If the remaining \(n > 1\), it is prime: record it.

Output: the prime factors of the original \(n\), with multiplicity.

def factorize(n):
    """Prime factorization by trial division: returns {prime: exponent}."""
    factors = {}
    d = 2
    while d * d <= n:
        while n % d == 0:
            factors[d] = factors.get(d, 0) + 1
            n //= d
        d += 1
    if n > 1:
        factors[n] = factors.get(n, 0) + 1
    return factors

print(factorize(360), factorize(97), factorize(1001), factorize(2**10 * 3**3))
{2: 3, 3: 2, 5: 1} {97: 1} {7: 1, 11: 1, 13: 1} {2: 10, 3: 3}

Worked example: is 391 prime? \(\sqrt{391} \approx 19.8\), so try primes up to 19. It isn’t even. Its digit sum is 13, so 3 fails. It doesn’t end in 0 or 5. \(391 = 7 \cdot 55 + 6\), so 7 fails. For 11, the alternating sum \(1 - 9 + 3 = -5\) is not a multiple of 11. \(391 = 13 \cdot 30 + 1\), so 13 fails. Then \(391 = 17 \cdot 23\). Composite. Numbers like this, a product of two primes of similar size, are exactly the kind RSA uses, just millions of times larger. Try it: Is 391 prime? Step through; Factorise 391.

Trial division doesn’t scale

Trial division takes about \(\sqrt{n}\) steps. For a 20-digit number that is \(10^{10}\) steps, which is a few seconds. For a 600-digit RSA modulus it is \(10^{300}\) steps, far more than the age of the universe on every computer ever built. Better factoring algorithms exist (the quadratic sieve and the general number field sieve), but none of them is remotely fast enough at that size. Multiplying is easy and factoring is hard. That asymmetry is the foundation of RSA.

23.2.5. How many primes are there?

Infinitely many. Euclid’s proof, about 300 BCE, is one of the first proofs anyone should see, and it appears in full in Chapter 22. In brief: given any finite list of primes, multiply them all together and add 1. The result leaves remainder 1 when divided by each listed prime, so its prime factors are all new. No finite list can be complete.

The primes also thin out. Among the first 100 integers, 25 are prime. Among the first million, 78,498 are. The prime number theorem (1896) says the number of primes up to \(n\) is roughly \(n / \ln n\). For \(n = 10^6\) that estimate gives about 72,382, which is low by 8% but captures the trend. Near a 300-digit number, roughly one integer in 690 is prime. That is plenty for RSA, which needs to find big primes quickly.

The largest known primes

The record primes are almost always Mersenne primes of the form \(2^p - 1\), because a fast special-purpose test (Lucas–Lehmer) exists for that shape. As of late 2024 the largest known was \(2^{136\,279\,841} - 1\), which has over 41 million digits. It was found by the volunteer GIMPS project running on cloud GPUs. In binary it is a string of 136,279,841 ones.

23.2.6. Where you’d use this

Everyday: common denominators. To add \(\tfrac{5}{12} + \tfrac{7}{18}\), factor: \(12 = 2^2 \cdot 3\) and \(18 = 2 \cdot 3^2\). The least common denominator takes the highest power of each prime, \(2^2 \cdot 3^2 = 36\), so the sum is \(\tfrac{15}{36} + \tfrac{14}{36} = \tfrac{29}{36}\). Uniqueness of factorization is what makes "highest power of each prime" a well-defined recipe.

Biology: prime-numbered life cycles. Periodical cicadas in North America spend 13 or 17 years underground and then emerge together in their billions. One leading explanation is arithmetic. A predator whose population peaks every 2, 3, 4, 5 or 6 years coincides with a 17-year brood only every \(\operatorname{lcm}\) of the two periods: 34, 51, 68, 85 or 102 years. A 12-year cicada would meet the 2-, 3-, 4- and 6-year predators every single emergence.

Engineering: hunting-tooth gears. A car’s final drive often pairs an 11-tooth pinion with a 41-tooth ring gear (ratio \(41/11 \approx 3.73\)). Because 41 is prime, the two counts share no factor, so a given pinion tooth meets every one of the 41 ring-gear teeth before any pairing repeats, after \(11 \times 41 = 451\) tooth engagements. Any manufacturing flaw on one tooth is spread over the whole gear instead of grinding the same spot.

Computing. Public-key cryptography rests on the asymmetry between multiplying two large primes (microseconds) and factoring the product (beyond any known classical computer for 2,048-bit numbers); Section 23.12 runs the numbers.

US curriculum

Primes, composites and prime factorization ("factor trees") belong to grades 4–6. Common Core 6.NS.B.4 uses factorization to find the greatest common factor and least common multiple. Infinitely many primes and the uniqueness of factorization are usually first proved in a college Discrete Mathematics or Number Theory course.

23.3. The sieve of Eratosthenes

23.3.1. The problem

Trial division tests one number at a time. Often you want all the primes up to some bound: to precompute a lookup table, to factor many small numbers, or to generate test data. Testing each of a million numbers separately repeats a lot of work. Can we share it?

23.3.2. Intuition

Turn the question around. Instead of asking "what divides this number?", ask "which numbers does this prime knock out?" Write down 2 through \(n\). The first number, 2, is prime, so cross out every multiple of 2 after it. The next number not crossed out, 3, must be prime, because nothing smaller divides it. Cross out its multiples. Then 5, then 7, and so on. Whatever survives is prime.

A 10 by 10 grid of the numbers 1 to 100 with the 25 primes highlighted in blue and composites shaded by the prime that first crossed them out
Figure 205. The sieve of Eratosthenes on 1–100. Every composite is crossed out by its smallest prime factor; only 2, 3, 5 and 7 are needed, since \(11^2 = 121 > 100\).

23.3.3. Why it works, and two shortcuts

A number survives exactly when no smaller prime divides it, and that is the definition of prime. Two refinements matter. Try it: Animate the sieve to 100.

  • Start crossing at \(p^2\). Any smaller multiple of \(p\), say \(kp\) with \(k < p\), has a prime factor smaller than \(p\) and was already crossed out.

  • Stop once \(p^2 > n\). By the square-root argument from trial division, every composite up to \(n\) has a prime factor at most \(\sqrt{n}\).

Example 121. Procedure — Sieve of Eratosthenes

Input: an integer \(n \ge 2\).

Steps:

  1. Make a table is_prime[0..n], all True. Set entries 0 and 1 to False.

  2. For \(p = 2, 3, 4, \ldots\) while \(p^2 \le n\):

    1. If is_prime[p] is still True, set is_prime[m] = False for \(m = p^2, p^2 + p, p^2 + 2p, \ldots \le n\).

  3. Collect every \(k\) with is_prime[k] true.

Output: the list of primes up to \(n\).

23.3.4. Worked example: primes up to 30

Start with 2 through 30. Since \(\sqrt{30} \approx 5.48\), only \(p = 2, 3, 5\) are needed. Try it: Sieve to 30 by rounds; The primes up to 30.

Step Crossed out

\(p = 2\) (start at 4)

4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30

\(p = 3\) (start at 9)

9, 15, 21, 27 (12, 18, 24, 30 were already gone)

\(p = 4\)

already crossed out, skip

\(p = 5\) (start at 25)

25 (30 already gone)

\(p = 6\)

\(36 > 30\), stop

Survivors: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29. Ten primes.

def sieve(n):
    """Return the list of primes <= n (sieve of Eratosthenes)."""
    if n < 2:
        return []
    is_prime = [True] * (n + 1)
    is_prime[0] = is_prime[1] = False
    p = 2
    while p * p <= n:
        if is_prime[p]:
            for multiple in range(p * p, n + 1, p):
                is_prime[multiple] = False
        p += 1
    return [k for k in range(n + 1) if is_prime[k]]

print(sieve(50))
print(len(sieve(1_000_000)))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
78498

23.3.5. Choosing a method

  • One number, small (up to about \(10^{12}\)): trial division up to \(\sqrt{n}\).

  • All primes up to \(n\), with \(n\) up to about \(10^8\): the sieve. It runs in about \(n \log\log n\) operations, which is nearly linear, but it needs \(n\) bits of memory. Segmented sieves process the range in cache-sized blocks.

  • One huge number (hundreds of digits): neither. Use a probabilistic test such as Miller–Rabin, which is built on Fermat’s little theorem (Section 23.9).

Sieve memory

A Python list of a billion booleans takes about 8 GB, because each entry is a pointer. Use bytearray(n + 1) (1 byte per entry) or a NumPy boolean array if you need big sieves. The algorithm is the same, but you get 8 times the reach.

Sieve as a pattern

The sieve is the first example many programmers meet of trading memory for time and of inverting a loop. Instead of "for each candidate, search for a divisor", it does "for each divisor, mark its multiples". The same inversion shows up in computing all divisor sums, in Euler’s totient sieve, in the smallest-prime-factor table that lets you factor any number up to \(n\) in \(O(\log n)\) steps, and in database-style "push" versus "pull" evaluation.

Watch the sieve

Animate the sieve on a 20 × 20 grid. Each prime colours its multiples in its own colour, starting at \(p^2\). Let the reader change the grid width. With width 6, the primes after 3 line up in just two columns (the numbers of the form \(6k \pm 1\)). With width 10, they fall in the columns ending 1, 3, 7, 9. Ask why: the other columns are multiples of 2 or 3, or of 2 or 5.

23.3.6. Exercises

  1. Which of these are prime: 91, 97, 119, 127? Explain how you know when to stop testing.

  2. Factorize 1001, 2024 and 5040 by trial division, showing each division.

  3. Run the sieve by hand up to 60. Which primes do you need to sieve with?

  4. Prove that every prime greater than 3 is of the form \(6k + 1\) or \(6k + 5\). (Consider the six possible remainders mod 6.)

Answers
  1. \(91 = 7 \cdot 13\) (composite). For 97, \(\sqrt{97} < 10\), and 2, 3, 5, 7 all fail (\(97 = 13\cdot7 + 6\)), so it is prime. \(119 = 7 \cdot 17\) (composite). For 127, \(\sqrt{127} < 12\), and 2, 3, 5, 7, 11 all fail (\(127 = 18 \cdot 7 + 1 = 11 \cdot 11 + 6\)), so it is prime. Stop once the trial divisor exceeds \(\sqrt{n}\).

  2. \(1001 = 7 \cdot 143 = 7 \cdot 11 \cdot 13\). \(2024 = 2 \cdot 1012 = 2^2 \cdot 506 = 2^3 \cdot 253 = 2^3 \cdot 11 \cdot 23\). \(5040 = 2^4 \cdot 315 = 2^4 \cdot 3^2 \cdot 35 = 2^4 \cdot 3^2 \cdot 5 \cdot 7\) (this is \(7!\)).

  3. \(\sqrt{60} < 8\), so sieve with 2, 3, 5 and 7 (7 first crosses out 49). Primes: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, which makes 17 of them.

  4. Any integer has remainder 0–5 mod 6. Remainders 0, 2, 4 make it even. Remainder 3 makes it a multiple of 3 (\(6k + 3 = 3(2k+1)\)). A prime greater than 3 is neither, so its remainder is 1 or 5.

23.4. Greatest common divisor and the Euclidean algorithm

23.4.1. The problem

To simplify the fraction \(\tfrac{462}{1071}\) you need the largest number dividing both. To tile a \(48 \times 18\) floor with identical square tiles and no cutting, you need the largest square side that divides both lengths. To find the period of two interlocking gears, or to normalise an aspect ratio such as \(1920 \times 1080 \to 16:9\), you need the same thing again: the greatest common divisor.

You could factor both numbers and compare. For \(462 = 2 \cdot 3 \cdot 7 \cdot 11\) and \(1071 = 3^2 \cdot 7 \cdot 17\), the shared part is \(3 \cdot 7 = 21\). But factoring is the hard problem we just met. For 300-digit numbers it is hopeless. Remarkably, there is an algorithm that finds the GCD without factoring anything, and it is about 2,300 years old.

GCD, coprime

The greatest common divisor \(\gcd(a, b)\) of two integers, not both zero, is the largest positive integer dividing both. US schools call it the greatest common factor (GCF), and UK schools the highest common factor (HCF). If \(\gcd(a, b) = 1\), then \(a\) and \(b\) are coprime (or relatively prime). They need not be prime themselves: 8 and 15 are coprime. By convention \(\gcd(a, 0) = |a|\).

23.4.2. Intuition: tiles

Take the \(48 \times 18\) rectangle. The biggest square you can cut from it is \(18 \times 18\), and you can fit two of them, leaving a \(12 \times 18\) strip. Any square tile that fits the original rectangle exactly also fits the squares (its side divides 18) and therefore fits the leftover strip. Conversely, a tile that fits the \(18 \times 12\) strip fits everything. So the problem has shrunk from \((48, 18)\) to \((18, 12)\) with the same answer. Repeat: one \(12 \times 12\) square leaves \(12 \times 6\). Then two \(6 \times 6\) squares fill it exactly. The answer is 6. Try it: Tile 48 × 18 with squares.

A 48 by 18 rectangle divided into two 18 by 18 squares, one 12 by 12 square, and two 6 by 6 squares
Figure 206. Euclid’s algorithm as tiling. Each step cuts off as many largest squares as fit; the last square size that tiles the leftover exactly is the GCD.

23.4.3. Why it works

The tiling picture is the following fact, written as algebra.

\[\gcd(a, b) = \gcd(b,\ a \bmod b) \qquad (b > 0).\]

Proof. Write \(a = qb + r\) with \(r = a \bmod b\). If \(d\) divides \(a\) and \(b\), it divides \(r = a - qb\), because that is an integer combination of \(a\) and \(b\). Conversely, if \(d\) divides \(b\) and \(r\), it divides \(a = qb + r\). So the pairs \((a, b)\) and \((b, r)\) have exactly the same common divisors, and in particular the same greatest one. \(\square\)

Each step replaces the pair with a strictly smaller remainder, and remainders can’t go below 0, so the process must stop. It stops when the remainder is 0, and then \(\gcd(g, 0) = g\).

Example 122. Procedure — Euclidean algorithm

Input: integers \(a, b \ge 0\), not both zero.

Steps:

  1. If \(b = 0\), return \(a\).

  2. Otherwise compute \(r = a \bmod b\).

  3. Replace \((a, b)\) with \((b, r)\) and go to step 1.

Output: \(\gcd(a, b)\), the last nonzero remainder.

23.4.4. Worked example: \(\gcd(1071, 462)\)

Every division is written out in full: Try it: gcd(1071, 462) as a trace; gcd and Bézout for 1071, 462.

\[\begin{aligned} 1071 &= 2 \cdot 462 + 147 &&\quad (2 \cdot 462 = 924,\ 1071 - 924 = 147)\\ 462 &= 3 \cdot 147 + 21 &&\quad (3 \cdot 147 = 441,\ 462 - 441 = 21)\\ 147 &= 7 \cdot 21 + 0 &&\quad (7 \cdot 21 = 147) \end{aligned}\]

The last nonzero remainder is 21, so \(\gcd(1071, 462) = 21\). It took three divisions, and nothing was factored. Check: \(1071 = 21 \cdot 51\) and \(462 = 21 \cdot 22\), and \(\gcd(51, 22) = 1\). So

\[\frac{462}{1071} = \frac{22}{51}.\]

As a trace table, which is how you’d debug it:

\(a\) \(b\) \(q = \lfloor a/b \rfloor\) \(r = a \bmod b\)

1071

462

2

147

462

147

3

21

147

21

7

0

21

0

—

(return 21)

def gcd(a, b):
    """Greatest common divisor of integers a, b (not both zero)."""
    a, b = abs(a), abs(b)
    while b != 0:
        a, b = b, a % b      # replace (a, b) with (b, remainder)
    return a

print(gcd(1071, 462), gcd(462, 1071), gcd(17, 5), gcd(0, 9))
21 21 1 9

Notice that gcd(462, 1071) works too. The first step computes \(462 \bmod 1071 = 462\) and simply swaps the pair. In real code, use math.gcd.

23.4.5. How fast is it?

Every two steps, the remainder at least halves. (If \(b \le a/2\), then \(r < b \le a/2\). If \(b > a/2\), then \(q = 1\) and \(r = a - b < a/2\).) So the number of steps is at most about \(2 \log_2 b\): around 2,000 divisions for 1,000-bit numbers, which takes microseconds. Compare that with the astronomically slow factoring approach.

The first analysed algorithm

The algorithm appears in Euclid’s Elements (Book VII, around 300 BCE), stated with lengths of line segments, just like our tiles. In 1844 Gabriel Lamé proved that the worst case is consecutive Fibonacci numbers. For example, \(\gcd(89, 55)\) takes 9 division steps because every quotient except the last is 1. His bound, at most five times the number of decimal digits, is often called the first worst-case analysis of an algorithm’s running time.

23.4.6. Alternative approaches and choosing one

  • Compare factorizations. \(\gcd\) takes each shared prime to the smaller exponent. This is fine when you already have the factorizations or the numbers are tiny, and it explains what the GCD is. Hopeless for big numbers.

  • Subtraction-only Euclid. Replace the larger number by the difference until the two are equal. It is correct, but slow when one number is much bigger: \(\gcd(10^9, 1)\) takes a billion steps.

  • Binary GCD (Stein’s algorithm). It uses only shifts and subtraction, exploiting \(\gcd(2a, 2b) = 2\gcd(a, b)\), and was attractive on hardware with slow division.

  • Euclid with remainders is the default for everything else.

23.4.7. The least common multiple

LCM

The least common multiple \(\operatorname{lcm}(a, b)\) is the smallest positive integer that both \(a\) and \(b\) divide. It is the "lowest common denominator" you used when adding fractions in Chapter 2.

Comparing factorizations shows what’s going on. GCD takes the minimum exponent of each prime and LCM takes the maximum. Since \(\min(x, y) + \max(x, y) = x + y\), multiplying the two gives back \(ab\):

\[\gcd(a, b) \cdot \operatorname{lcm}(a, b) = a \cdot b, \qquad\text{so}\qquad \operatorname{lcm}(a, b) = \frac{a \cdot b}{\gcd(a, b)}.\]

Worked example. For \(a = 252 = 2^2 \cdot 3^2 \cdot 7\) and \(b = 198 = 2 \cdot 3^2 \cdot 11\): Try it: gcd and lcm of 252, 198; gcd and lcm of 252, 198.

\[\begin{aligned} 252 &= 1 \cdot 198 + 54\\ 198 &= 3 \cdot 54 + 36\\ 54 &= 1 \cdot 36 + 18\\ 36 &= 2 \cdot 18 + 0 &&\Rightarrow \gcd = 18\\[4pt] \operatorname{lcm}(252, 198) &= \frac{252 \cdot 198}{18} = 252 \cdot 11 = 2772. \end{aligned}\]

The factorizations agree: the GCD is \(2^1 \cdot 3^2 = 18\) and the LCM is \(2^2 \cdot 3^2 \cdot 7 \cdot 11 = 2772\).

Overflow in lcm

In fixed-width integer languages, compute a / gcd(a, b) * b, not a * b / gcd(a, b). The product \(ab\) can overflow even when the LCM itself fits.

Applications: two cron jobs running every 6 and every 10 minutes coincide every \(\operatorname{lcm}(6, 10) = 30\) minutes. Gears with 12 and 18 teeth return to their starting alignment after \(\operatorname{lcm}(12,18) = 36\) tooth-passes. Planetary conjunctions and traffic-light cycles work the same way.

Computer-science connection: GCD everywhere
  • Fractions and rationals: Python’s fractions.Fraction calls gcd on every operation to keep results in lowest terms.

  • Aspect ratios and pixel art: \(1920 \times 1080\) reduces by \(\gcd = 120\) to \(16 \times 9\).

  • Rotating an array in place: the "juggling" algorithm rotates an array of length \(n\) by \(k\) in \(\gcd(n, k)\) independent cycles.

  • RSA: key generation needs \(\gcd(e, \varphi) = 1\) and a modular inverse. That is the next section.

US curriculum

GCF and LCM by listing or factor trees: grade 6 (Common Core 6.NS.B.4). The Euclidean algorithm itself is rarely taught in US schools. It turns up in Discrete Mathematics (college, or high-school electives), in competition math, and in AP Computer Science as a recursion example.

23.5. Extended Euclid and Bézout’s identity

23.5.1. The problem

Here is a puzzle with a long history. You have a 1,071 ml jug and a 462 ml jug and unlimited water. Can you measure exactly 21 ml? Measuring means pouring whole jugfuls in and out of a tank, so the amounts you can reach are \(1071x + 462y\) for integers \(x, y\), where negative means "poured out". The real question is which numbers can be written as \(1071x + 462y\), and with which \(x\) and \(y\).

This isn’t just a puzzle. Finding such \(x, y\) is the way to compute modular inverses (Section 23.8), and modular inverses are how RSA keys get made.

23.5.2. Intuition

Every number of the form \(1071x + 462y\) is a multiple of 21, because 21 divides both terms. So you can’t measure 10 ml or 20 ml. The surprise is the converse: 21 itself is reachable, so every multiple of 21 is too. The Euclidean algorithm’s divisions, read backwards, tell you exactly how.

Bézout’s identity

For integers \(a, b\), not both zero, there exist integers \(x, y\) with

\[ax + by = \gcd(a, b).\]

The \(x, y\) are Bézout coefficients. They are not unique. A linear combination of \(a\) and \(b\) is any expression \(ax + by\). The integer combinations of \(a\) and \(b\) are exactly the multiples of \(\gcd(a, b)\).

23.5.3. The method: back-substitution

Take the divisions from the \(\gcd(1071, 462)\) example and solve each one for its remainder: Try it: Back-substitution, line by line; Check the Bézout coefficients.

\[\begin{aligned} 147 &= 1071 - 2 \cdot 462\\ 21 &= 462 - 3 \cdot 147 \end{aligned}\]

Now start from the last line, which already expresses the GCD, and substitute the line above for 147:

\[\begin{aligned} 21 &= 462 - 3 \cdot 147\\ &= 462 - 3 \cdot (1071 - 2 \cdot 462) &&\text{(substitute for 147)}\\ &= 462 - 3 \cdot 1071 + 6 \cdot 462 &&\text{(expand)}\\ &= 7 \cdot 462 - 3 \cdot 1071 &&\text{(collect the 462s)} \end{aligned}\]

So \(x = -3\) and \(y = 7\). Check: \(7 \cdot 462 = 3234\), \(3 \cdot 1071 = 3213\), and \(3234 - 3213 = 21\). With the jugs: fill the small jug 7 times into the tank and empty out the large jug’s worth 3 times.

23.5.4. A forward version for programs

Back-substitution means storing every line. Code usually keeps a running pair instead. It tracks how each remainder is written in terms of the original \(a\) and \(b\), and updates that alongside the remainders. Each row satisfies \(r_i = a x_i + b y_i\). Try it: The forward extended-Euclid table.

\(q\) \(r\) \(x\) \(y\) Check \(1071x + 462y\)

1071

1

0

1071

462

0

1

462

2

147

\(1 - 2\cdot0 = 1\)

\(0 - 2\cdot1 = -2\)

\(1071 - 924 = 147\)

3

21

\(0 - 3\cdot1 = -3\)

\(1 - 3\cdot(-2) = 7\)

\(-3213 + 3234 = 21\)

7

0

\(1 - 7\cdot(-3) = 22\)

\(-2 - 7\cdot7 = -51\)

\(23562 - 23562 = 0\)

Each new row equals (the row two above) minus \(q\) times (the row above), with \(q\) being the quotient of the two remainders above it. The row just before the 0 gives the GCD and its coefficients.

Example 123. Procedure — Extended Euclidean algorithm

Input: integers \(a, b \ge 0\), not both zero.

Steps:

  1. Start with two rows: \((r, x, y) = (a, 1, 0)\) and \((b, 0, 1)\).

  2. While the latest \(r \ne 0\):

    1. Let \(q = \lfloor r_\text{prev} / r_\text{latest} \rfloor\).

    2. New row = previous row \(-\ q \times\) latest row (applied to each of \(r, x, y\)).

  3. The last row with \(r \ne 0\) is \((g, x, y)\).

Output: \(g = \gcd(a, b)\) and \(x, y\) with \(ax + by = g\).

def extended_gcd(a, b):
    """Return (g, x, y) with g = gcd(a, b) and a*x + b*y == g."""
    old_r, r = a, b
    old_x, x = 1, 0
    old_y, y = 0, 1
    while r != 0:
        q = old_r // r
        old_r, r = r, old_r - q * r
        old_x, x = x, old_x - q * x
        old_y, y = y, old_y - q * y
    return old_r, old_x, old_y

print(extended_gcd(1071, 462))
(21, -3, 7)

23.5.5. Why it matters: Euclid’s lemma

We promised a proof of unique factorization. Here is the missing piece.

Euclid’s lemma

If a prime \(p\) divides a product \(ab\), then \(p \mid a\) or \(p \mid b\).

Proof. Suppose \(p \nmid a\). The only positive divisors of \(p\) are 1 and \(p\), so \(\gcd(p, a) = 1\). By Bézout, \(px + ay = 1\) for some integers \(x, y\). Multiply through by \(b\):

\[pbx + aby = b.\]

\(p\) divides \(pbx\) obviously, and \(p\) divides \(aby\) because \(p \mid ab\). So \(p\) divides their sum, which is \(b\). \(\square\)

The lemma needs \(p\) prime: \(6 \mid 4 \cdot 9\) but \(6 \nmid 4\) and \(6 \nmid 9\). That one fact is why primes behave like atoms.

Bézout coefficients are not unique

If \((x, y)\) works, so does \(\left(x + k\tfrac{b}{g},\ y - k\tfrac{a}{g}\right)\) for every integer \(k\). From the table, \((-3, 7)\) and \((-3 + 22,\ 7 - 51) = (19, -44)\) both give 21. Different libraries can return different (equally correct) pairs. When you need a canonical answer, such as a modular inverse in the range \(0..m-1\), reduce at the end.

Jug puzzles

Build a two-jug simulator: choose capacities \(a\) and \(b\) and allow fill, empty and pour. Highlight the reachable amounts. The reader should discover that exactly the multiples of \(\gcd(a, b)\) (up to the larger capacity) are reachable. This is the Die Hard 3 puzzle: measure 4 gallons with 3- and 5-gallon jugs. Show the Bézout coefficients the path corresponds to.

23.5.6. Exercises

  1. Use the Euclidean algorithm to find \(\gcd(84, 120)\) and \(\gcd(89, 55)\). How many division steps does each take?

  2. Find integers \(x, y\) with \(240x + 46y = \gcd(240, 46)\), using back-substitution, and check your answer. Try it: Check 240x + 46y = 2.

  3. Compute \(\operatorname{lcm}(84, 120)\) two ways.

  4. Can a 6-litre and a 15-litre jug measure exactly 4 litres? 9 litres? Explain with Bézout. Try it: Try the 6- and 15-litre jugs.

  5. Show that consecutive integers \(n\) and \(n+1\) are always coprime.

Answers
  1. \(120 = 1 \cdot 84 + 36\), \(84 = 2 \cdot 36 + 12\), \(36 = 3 \cdot 12 + 0\), so the GCD is 12 in 3 steps. For \((89, 55)\), every quotient except the last is 1: the remainders run 34, 21, 13, 8, 5, 3, 2, 1, 0, so the GCD is 1 in 9 steps. This is Lamé’s Fibonacci worst case.

  2. \(240 = 5\cdot46 + 10\), \(46 = 4\cdot10 + 6\), \(10 = 1\cdot6 + 4\), \(6 = 1\cdot4 + 2\), \(4 = 2\cdot2\), so the GCD is 2. Back-substitute: \(2 = 6 - 4 = 6 - (10 - 6) = 2\cdot6 - 10 = 2(46 - 4\cdot10) - 10 = 2\cdot46 - 9\cdot10 = 2\cdot46 - 9(240 - 5\cdot46) = 47\cdot46 - 9\cdot240\). So \(x = -9\), \(y = 47\). Check: \(47\cdot46 = 2162\) and \(9 \cdot 240 = 2160\), difference 2.

  3. \(84 \cdot 120 / 12 = 840\). By factorization: \(84 = 2^2\cdot3\cdot7\) and \(120 = 2^3\cdot3\cdot5\). Taking maximum exponents gives \(2^3\cdot3\cdot5\cdot7 = 840\).

  4. \(\gcd(6, 15) = 3\). Reachable amounts are multiples of 3, so 4 litres is impossible and 9 litres is possible. For example, \(9 = 6 \cdot (-1) + 15 \cdot 1\): fill the 15 and pour off 6.

  5. Any common divisor \(d\) divides \((n + 1) - n = 1\), so \(d = 1\). In Bézout form, \((n+1)\cdot 1 + n \cdot(-1) = 1\).

23.6. Modular arithmetic: clock arithmetic made precise

23.6.1. The problem

It is 9 o’clock. What time will it be in 5 hours? Nobody says "14 o’clock" on a 12-hour clock. You say 2. In 100 hours? You don’t count 100 ticks. You throw away whole 12-hour laps. A 32-bit counter at \(2^{32} - 1\) that gets incremented becomes 0. The day of the week, the angle of a rotating wheel, the slot in a ring buffer: these are all quantities where only the remainder matters.

Modular arithmetic is the algebra of "only the remainder matters". The surprise is how much ordinary algebra still works there, and the one rule that doesn’t.

23.6.2. Intuition: wrapping the number line

Wrap the number line around a circle of circumference 12. Then 2, 14, 26 and \(-10\) all land on the same spot. Adding means walking clockwise. Subtracting means walking anticlockwise. Multiplying is repeated addition. Try it: 9 + 5 on a clock.

A clock face numbered 0 to 11 with an arc from 9 forward five steps to 2
Figure 207. Arithmetic modulo 12: starting at 9 and walking 5 steps lands on 2, because 14 and 2 differ by a full lap of 12.

23.6.3. Vocabulary and notation

Congruence modulo \(m\)

Fix a positive integer \(m\), the modulus. Integers \(a\) and \(b\) are congruent modulo \(m\), written

\[a \equiv b \pmod{m},\]

if \(m \mid (a - b)\). Equivalently, \(a\) and \(b\) leave the same remainder when divided by \(m\). Read it as "\(a\) is congruent to \(b\) mod \(m\)". For example, \(14 \equiv 2 \pmod{12}\), \(-10 \equiv 2 \pmod{12}\), and \(100 \equiv 4 \pmod{12}\).

The three-bar symbol \(\equiv\) was Gauss’s choice (1801). It looks like "=" on purpose.

mod as an operator vs. mod as a context

The same word does two jobs. \(17 \bmod 5 = 2\) uses mod as an operator: a function that returns a number, like % in code. \(17 \equiv 2 \pmod 5\) uses mod as a context: a statement about two numbers, and the "(mod 5)" applies to the whole line. So \(17 \equiv 7 \pmod 5\) is true, but \(17 \bmod 5 = 7\) is false.

Residue, residue class

The residue of \(a\) mod \(m\) is the remainder \(a \bmod m\), one of \(0, 1, \ldots, m-1\). The residue class \(\lbrack a]_m\) is the set of all integers congruent to \(a\). For example, \(\lbrack 2]_{12} = \{\ldots, -10, 2, 14, 26, \ldots\}\). There are exactly \(m\) classes, and the set of them is written \(\mathbb{Z}_m\) or \(\mathbb{Z}/m\mathbb{Z}\).

Integers from -6 to 11 arranged in three columns according to their remainder mod 3
Figure 208. The integers sorted into residue classes mod 3. Congruent numbers sit in the same column; arithmetic mod 3 is arithmetic on columns.

Congruence is an equivalence relation (reflexive, symmetric and transitive; see Chapter 21). That is the formal reason the "columns" picture is legitimate. Each integer belongs to exactly one column.

23.6.4. Why it works: congruences respect + − ×

Here is the key theorem. Suppose \(a \equiv a'\) and \(b \equiv b' \pmod m\). Then

\[a + b \equiv a' + b', \qquad a - b \equiv a' - b', \qquad ab \equiv a'b' \pmod m.\]

Why. Write \(a' = a + km\) and \(b' = b + lm\). Then

\[\begin{aligned} a' + b' &= (a + b) + (k + l)m &&\text{(differs from } a + b \text{ by a multiple of } m)\\ a'b' &= (a + km)(b + lm)\\ &= ab + alm + bkm + klm^2 &&\text{(expand)}\\ &= ab + m(al + bk + klm) &&\text{(factor out } m). \end{aligned}\]

In practice this means you may reduce at any point. Replace any number by its remainder whenever you like, and the final remainder comes out the same. That is what makes huge computations tractable: intermediate values never need to grow past \(m^2\).

Worked example. What is the last digit of \(7 \cdot 13 \cdot 29 \cdot 48\)? "Last digit" means "mod 10".

\[\begin{aligned} 7 \cdot 13 &= 91 \equiv 1 \pmod{10}\\ 1 \cdot 29 &= 29 \equiv 9\\ 9 \cdot 48 &\equiv 9 \cdot 8 = 72 \equiv 2 \pmod{10}. \end{aligned}\]

The last digit is 2. You never needed the full product, which is 126,672.

23.6.5. Divisibility tests, explained

Since \(10 \equiv 1 \pmod 9\), every power \(10^k \equiv 1^k = 1 \pmod 9\). A number with digits \(d_k \ldots d_1 d_0\) is \(\sum d_i 10^i\). (Here \(\sum\) means "add up the following terms over all values of \(i\)".) So

\[d_k 10^k + \cdots + d_1 10 + d_0 \equiv d_k + \cdots + d_1 + d_0 \pmod 9.\]

A number and its digit sum leave the same remainder mod 9, and therefore also mod 3. Similarly, \(10 \equiv -1 \pmod{11}\), so \(10^k \equiv (-1)^k\) and the alternating digit sum gives the remainder mod 11. Old-school "casting out nines" to check hand multiplication is the same idea.

23.6.6. The one rule that breaks: division

In ordinary arithmetic, \(2x = 2y\) lets you cancel the 2. Mod 6, though, Try it: Zero divisors mod 6.

\[2 \cdot 1 \equiv 2 \cdot 4 \pmod 6 \quad (2 \equiv 8), \qquad\text{but}\qquad 1 \not\equiv 4 \pmod 6.\]

You can’t cancel 2, because 2 shares a factor with 6. Worse, \(2 \cdot 3 = 6 \equiv 0 \pmod 6\): two nonzero numbers multiply to zero. These are called zero divisors. Division mod \(m\) works only for numbers coprime to \(m\), and modular inverses (Section 23.8) make that precise.

23.6.7. Where you’d use this

Time and calendars. A flight leaves at 21:00 and the journey, including a stopover, takes 50 hours. Arrival is at \(21 + 50 = 71 \equiv 23 \pmod{24}\), so 23:00, and \(\lfloor 71/24 \rfloor = 2\) days later. Days of the week work mod 7: since \(365 = 52 \cdot 7 + 1 \equiv 1 \pmod 7\), a date moves one weekday later each ordinary year (two after a leap day). Christmas 2026 is a Friday, so Christmas 2027 is a Saturday.

Navigation and physics. Compass bearings live mod 360: a ship on heading 350° that turns 30° to starboard is on heading \(380 \bmod 360 = 20\)°. Phase angles of waves and alternating currents live mod \(2\pi\) (see Chapter 13), which is why a phase of \(370°\) and one of \(10°\) describe the same signal.

Music. Western pitch classes are residues mod 12: an octave is 12 semitones, a perfect fifth is 7. Stepping up by fifths gives \(0, 7, 14 \equiv 2, 9, 16 \equiv 4, \ldots\); because \(\gcd(7, 12) = 1\) the walk visits all 12 pitch classes before returning to the start. That walk is the circle of fifths. Stepping by 4 semitones (a major third) instead, with \(\gcd(4, 12) = 4\), cycles through only 3 notes.

Computer-science connection: your CPU is a modular arithmetic machine

An unsigned 32-bit integer is a residue mod \(2^{32}\). Addition, subtraction and multiplication in C (for unsigned types), Java, Rust’s wrapping_* operations and GPUs are all exactly arithmetic in \(\mathbb{Z}_{2^{32}}\). The congruence rules above guarantee that the low 32 bits of a result depend only on the low 32 bits of the inputs. Two’s complement signed integers are the same residues with a different choice of representatives: \(-2^{31} \ldots 2^{31}-1\) instead of \(0 \ldots 2^{32}-1\). That is why the CPU can use one adder circuit for both.

Practical consequences:

  • x % 2k == x & (2k - 1) for nonnegative x, which is why hash tables love power-of-two sizes.

  • A ring buffer’s index is (head + i) % capacity.

  • Overflowing multiplication in a hash function doesn’t "go wrong". It just works mod \(2^{64}\).

Any modulus clock

A clock face with an adjustable modulus \(m\). The user picks \(a\) and \(b\) and sees \(a + b\) and \(a \cdot b\) as walks around the dial. A second mode draws the "times \(k\)" map as chords: connect each \(x\) to \(kx \bmod m\). With \(m = 200, k = 2\) you get a cardioid, and other \(k\) give nephroids and stranger curves. It is a striking picture of multiplication as rotation.

23.7. What % means for negative numbers

23.7.1. The problem

Ask Python and C the same question: Try it: % on negatives, language by language.

Expression Python C, C++, Java, JavaScript, Go, Rust (%)

7 / 2 (integer) and 7 % 2

3, 1

3, 1

-7 / 2 and -7 % 2

-4, 1

-3, -1

7 / -2 and 7 % -2

-4, -1

-3, 1

(In Python, integer division is //.) Both camps are internally consistent. They disagree on which quotient to pick.

23.7.2. Why: two rounding rules

Every language preserves the identity

\[a = b \cdot q + r,\]

so choosing \(q\) determines \(r\). For \(-7 / 2 = -3.5\) there are two natural choices:

  • Truncate toward zero (C99 and later, Java, JavaScript, Go, Rust): \(q = -3\). Then \(r = -7 - (2)(-3) = -1\). The remainder takes the sign of the dividend.

  • Floor, toward \(-\infty\) (Python, Ruby, Haskell’s mod, mathematics): \(q = \lfloor -3.5 \rfloor = -4\). Then \(r = -7 - (2)(-4) = 1\). The remainder takes the sign of the divisor, so for positive \(m\) it always lies in \(0 \ldots m-1\), matching the division algorithm.

Floor and truncation

The floor \(\lfloor x \rfloor\) is the greatest integer \(\le x\): \(\lfloor 3.5 \rfloor = 3\) and \(\lfloor -3.5 \rfloor = -4\). Truncation drops the fractional part, rounding toward 0: \(-3.5 \to -3\). They agree for nonnegative numbers and differ for negative non-integers.

print(7 // 2, 7 % 2, -7 // 2, -7 % 2, 7 // -2, 7 % -2)
import math
print(math.fmod(-7, 2), int(-7 / 2))
3 1 -4 1 -4 -1
-1.0 -3

Python’s math.fmod and int(a / b) give you the C-style behaviour when you need it. Be careful with int(a / b) for huge integers, though, since it goes through floating point.

The negative-index bug

In C, Java or JavaScript, arr[(i - 1) % n] with i = 0 computes -1 % n == -1. That is an out-of-bounds index, or worse, a silent read from the end of the array in languages with negative indexing. The portable fix is

((i - 1) % n + n) % n

or Math.floorMod(i - 1, n) in Java, or i.rem_euclid(n) in Rust. The same bug breaks "is odd" tests: x % 2 == 1 is false for x = -3 in C and Java. Write x % 2 != 0 instead.

Choosing a convention

Use floor (Python-style) whenever the remainder is used as an index, a bucket, a day of the week or a clock position. You want \(0 \ldots m-1\) every time. Truncation survives mainly because early hardware divide instructions worked that way and C standardised it. Wherever correctness matters, write a mod(a, m) helper and use it everywhere rather than trusting %.

23.8. Modular inverses and linear congruences

23.8.1. The problem

Solve \(7x \equiv 3 \pmod{26}\). In ordinary arithmetic you’d divide by 7. Mod 26 there are no fractions, so what does "divide by 7" even mean? We need a whole number that acts like \(\tfrac{1}{7}\): something that, multiplied by 7, gives 1.

Modular inverse

An inverse of \(a\) modulo \(m\) is an integer \(a^{-1}\) with

\[a \cdot a^{-1} \equiv 1 \pmod m.\]

It exists if and only if \(\gcd(a, m) = 1\), and it is unique mod \(m\). For example, \(3^{-1} \equiv 4 \pmod{11}\) because \(3 \cdot 4 = 12 \equiv 1\). The notation \(a^{-1}\) here never means the fraction \(1/a\).

23.8.2. Why gcd 1 is exactly the condition

  • If \(\gcd(a, m) = 1\): Bézout gives \(ax + my = 1\). Read it mod \(m\). The \(my\) term is a multiple of \(m\), so \(ax \equiv 1\). The Bézout coefficient \(x\) is the inverse.

  • If \(\gcd(a, m) = g > 1\): every \(ax + my\) is a multiple of \(g\), so it can never equal 1, and no inverse exists.

The two multiplication tables below show this. Mod 7 (a prime) every nonzero row contains exactly one 1. Mod 8, the rows for 2, 4 and 6, which share a factor with 8, never reach 1 and even hit 0.

Two multiplication tables side by side; in the mod 7 table every row has a highlighted 1, in the mod 8 table the even rows have none
Figure 209. Multiplication tables mod 7 and mod 8. A 1 in row \(a\) marks its inverse. Mod a prime, every nonzero element has one.
Example 124. Procedure — Modular inverse

Input: integers \(a\) and \(m > 1\).

Steps:

  1. Run the extended Euclidean algorithm on \((m, a)\) to get \(g\) and coefficients with \(m\cdot s + a \cdot t = g\).

  2. If \(g \ne 1\), stop: \(a\) has no inverse mod \(m\).

  3. Otherwise return \(t \bmod m\), reduced into \(0 \ldots m-1\).

Output: \(a^{-1} \bmod m\).

23.8.3. Worked example: \(7^{-1} \pmod{26}\)

Euclid on \((26, 7)\): Try it: 7⁻¹ mod 26, step by step; Compute 7⁻¹ mod 26.

\[\begin{aligned} 26 &= 3 \cdot 7 + 5\\ 7 &= 1 \cdot 5 + 2\\ 5 &= 2 \cdot 2 + 1\\ 2 &= 2 \cdot 1 + 0 &&\Rightarrow \gcd = 1,\ \text{an inverse exists.} \end{aligned}\]

Back-substitute, starting from the line that produced 1:

\[\begin{aligned} 1 &= 5 - 2 \cdot 2\\ &= 5 - 2 \cdot (7 - 5) &&\text{(} 2 = 7 - 5 \text{)}\\ &= 3 \cdot 5 - 2 \cdot 7\\ &= 3 \cdot (26 - 3 \cdot 7) - 2 \cdot 7 &&\text{(} 5 = 26 - 3\cdot 7 \text{)}\\ &= 3 \cdot 26 - 11 \cdot 7. \end{aligned}\]

Mod 26 the \(3 \cdot 26\) term vanishes, leaving \(-11 \cdot 7 \equiv 1\). So \(7^{-1} \equiv -11 \equiv 15 \pmod{26}\). Check: \(7 \cdot 15 = 105 = 4 \cdot 26 + 1\). Correct.

Now solve \(7x \equiv 3 \pmod{26}\) by multiplying both sides by 15:

\[x \equiv 15 \cdot 3 = 45 \equiv 19 \pmod{26}.\]

Check: \(7 \cdot 19 = 133 = 5 \cdot 26 + 3\). Correct.

def mod_inverse(a, m):
    g, x, _ = extended_gcd(a, m)
    if g != 1:
        raise ValueError(f"{a} has no inverse mod {m} (gcd is {g})")
    return x % m

print(mod_inverse(3, 40), mod_inverse(17, 3120), mod_inverse(7, 26))
print(pow(17, -1, 3120))      # Python 3.8+ does it for you
27 2753 15
2753

(mod_inverse reuses extended_gcd from Section 23.5. Here \(x\) is the coefficient of \(a\), which is the one we want.)

23.8.4. When \(\gcd > 1\): linear congruences in general

\(ax \equiv b \pmod m\) has solutions exactly when \(g = \gcd(a, m)\) divides \(b\). In that case, divide everything by \(g\) and solve the smaller congruence, which gives \(g\) solutions mod \(m\). Example: \(4x \equiv 6 \pmod{10}\). Here \(g = 2\) divides 6, so dividing by 2 gives \(2x \equiv 3 \pmod 5\). Since \(2^{-1} \equiv 3 \pmod 5\), we get \(x \equiv 9 \equiv 4 \pmod 5\). Mod 10 that means \(x \in \{4, 9\}\). Check: \(16 \equiv 6\) and \(36 \equiv 6 \pmod{10}\). In contrast, \(4x \equiv 5 \pmod{10}\) has no solutions, since \(4x\) is always even and so is \(10\): the difference would be odd. Try it: Solve 4x ≡ 6 (mod 10).

Primes make perfect number systems

When \(p\) is prime, every nonzero element of \(\mathbb{Z}_p\) has an inverse, so you can add, subtract, multiply and divide, just as with the rationals. Mathematicians call that a field, and \(\mathbb{Z}_p\) is the finite field \(\mathbb{F}_p\). Reed–Solomon codes (QR codes, CDs, deep-space probes), elliptic-curve cryptography and AES all do their arithmetic in finite fields.

Computer-science connection: the Chinese remainder theorem

If \(m_1, m_2\) are coprime, a number mod \(m_1 m_2\) is completely determined by its two residues mod \(m_1\) and mod \(m_2\). Inverses let you reconstruct it. This Chinese remainder theorem (Sunzi, 3rd–5th century CE) is how RSA implementations speed up decryption about fourfold: they work mod \(p\) and mod \(q\) separately. It is also how "residue number systems" do wide-integer arithmetic in parallel channels.

23.9. Fermat’s little theorem

23.9.1. The problem

Compute the powers of 3 mod 7: \(3, 2, 6, 4, 5, 1, 3, 2, 6, \ldots\) The sequence repeats with period 6. Powers of 2 mod 7 go \(2, 4, 1, 2, 4, 1, \ldots\) with period 3. Both periods divide 6, which is one less than the prime 7. Coincidence?

Fermat’s little theorem

If \(p\) is prime and \(p \nmid a\), then

\[a^{p-1} \equiv 1 \pmod p.\]

Equivalently, \(a^p \equiv a \pmod p\) for every integer \(a\). ("Little" distinguishes it from Fermat’s Last Theorem.)

23.9.2. Why it works: shuffling the nonzero residues

Take \(p = 7\), \(a = 3\), and multiply each of \(1, 2, 3, 4, 5, 6\) by 3, mod 7:

\[3,\ 6,\ 9 \equiv 2,\ 12 \equiv 5,\ 15 \equiv 1,\ 18 \equiv 4.\]

You get \(3, 6, 2, 5, 1, 4\), which is the same six numbers in a different order. That always happens. If \(ai \equiv aj\), multiplying by \(a^{-1}\) gives \(i \equiv j\), so no two products collide, and none is 0. Now multiply all six products together. They’re the same numbers, so they have the same product:

\[\begin{aligned} (3\cdot1)(3\cdot2)(3\cdot3)(3\cdot4)(3\cdot5)(3\cdot6) &\equiv 1\cdot2\cdot3\cdot4\cdot5\cdot6 \pmod 7\\ 3^6 \cdot 6! &\equiv 6! \pmod 7\\ 3^6 &\equiv 1 \pmod 7 &&\text{(cancel } 6!\text{, which is coprime to 7)} \end{aligned}\]

Replace 7 by \(p\) and 3 by \(a\) and the argument is the general proof.

23.9.3. Using it: shrinking exponents

Fermat lets you reduce an exponent mod \(p - 1\).

Worked example: \(3^{100} \bmod 7\). Since \(3^6 \equiv 1\) and \(100 = 16 \cdot 6 + 4\): Try it: Compute 3¹⁰⁰ mod 7.

\[3^{100} = (3^6)^{16} \cdot 3^4 \equiv 1^{16} \cdot 81 \equiv 81 - 77 = 4 \pmod 7.\]

Worked example: \(7^{222} \bmod 11\). \(7^{10} \equiv 1\) and \(222 = 22 \cdot 10 + 2\), so \(7^{222} \equiv 7^2 = 49 \equiv 5 \pmod{11}\).

23.9.4. Euler’s generalisation

For a composite modulus, replace \(p - 1\) with Euler’s totient \(\varphi(n)\), the count of numbers in \(1 \ldots n\) that are coprime to \(n\). Euler’s theorem: if \(\gcd(a, n) = 1\), then \(a^{\varphi(n)} \equiv 1 \pmod n\). For a prime, \(\varphi(p) = p - 1\). For a product of two distinct primes, \(\varphi(pq) = (p-1)(q-1)\): of the \(pq\) numbers, the \(q\) multiples of \(p\) and the \(p\) multiples of \(q\) are excluded, and \(pq\) itself was counted twice, so \(pq - p - q + 1 = (p-1)(q-1)\). RSA is built on this formula.

23.9.5. Primality testing

Turn the theorem around. If \(a^{n-1} \not\equiv 1 \pmod n\) for some \(a\), then \(n\) is definitely composite, and we learned that without finding a factor. For example, \(2^{14} = 16384 = 1092 \cdot 15 + 4\), so \(2^{14} \equiv 4 \not\equiv 1 \pmod{15}\) and 15 is composite.

def fermat_probably_prime(n, bases=(2, 3, 5, 7)):
    return all(pow(a, n - 1, n) == 1 for a in bases if a % n != 0)

print([k for k in range(2, 40) if fermat_probably_prime(k)])
print(pow(2, 560, 561), 561 == 3 * 11 * 17)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
1 True
Passing the Fermat test does not prove primality

The theorem only goes one way: prime implies \(a^{p-1} \equiv 1\). The converse is false. \(561 = 3 \cdot 11 \cdot 17\) satisfies \(a^{560} \equiv 1 \pmod{561}\) for every \(a\) coprime to 561. Numbers like this are Carmichael numbers, and there are infinitely many of them. Real libraries use the Miller–Rabin test, a strengthened Fermat test with no such blind spots. Each random base catches a composite with probability at least \(3/4\), so 40 rounds leave an error chance below \(2^{-80}\). (Confusing a theorem with its converse is a classic logic error; see Chapter 21.)

23.10. Fast modular exponentiation

23.10.1. The problem

RSA needs things like \(m^{65537} \bmod n\) with \(n\) around 600 digits long. Computing \(m^{65537}\) first is absurd: the number would have about 40 million digits before you reduced it. Multiplying by \(m\) 65,536 times, reducing as you go, keeps numbers small but takes too many steps once exponents are themselves 600 digits long. We need something exponentially better.

23.10.2. Intuition: square, don’t multiply

Squaring doubles the exponent: \(a \to a^2 \to a^4 \to a^8 \to \cdots\). After 10 squarings you have \(a^{1024}\). Any exponent is a sum of powers of 2, its binary expansion, so multiply together the squarings you need:

\[13 = 8 + 4 + 1 = 1101_2 \quad\Rightarrow\quad a^{13} = a^8 \cdot a^4 \cdot a^1.\]

An \(n\)-bit exponent needs at most \(n\) squarings and \(n\) multiplications. For a 2048-bit exponent that is about 4,000 operations instead of \(2^{2048}\). Reducing mod \(m\) after each step (allowed by Section 23.6) keeps every number below \(m^2\).

Example 125. Procedure — Square-and-multiply (right-to-left binary exponentiation)

Input: base \(a\), exponent \(e \ge 0\), modulus \(m\).

Steps:

  1. Set \(\text{result} = 1\) and \(\text{base} = a \bmod m\).

  2. While \(e > 0\):

    1. If the lowest bit of \(e\) is 1 (\(e\) odd): \(\text{result} \leftarrow \text{result} \cdot \text{base} \bmod m\).

    2. \(\text{base} \leftarrow \text{base}^2 \bmod m\).

    3. \(e \leftarrow \lfloor e / 2 \rfloor\) (shift right one bit).

Output: \(a^e \bmod m\).

23.10.3. Worked example: \(7^{13} \bmod 11\)

First tabulate the repeated squares of 7 mod 11: Try it: 7¹³ mod 11, bit by bit; Compute 7¹³ mod 11.

\[\begin{aligned} 7^1 &\equiv 7\\ 7^2 &= 49 = 4 \cdot 11 + 5 \equiv 5\\ 7^4 &\equiv 5^2 = 25 = 2 \cdot 11 + 3 \equiv 3\\ 7^8 &\equiv 3^2 = 9. \end{aligned}\]

Since \(13 = 8 + 4 + 1\), multiply the matching rows and reduce at each step:

\[\begin{aligned} 7^{13} &= 7^8 \cdot 7^4 \cdot 7^1\\ &\equiv 9 \cdot 3 \cdot 7\\ &= 27 \cdot 7 \equiv 5 \cdot 7 &&(27 = 2\cdot 11 + 5)\\ &= 35 \equiv 2 \pmod{11} &&(35 = 3 \cdot 11 + 2). \end{aligned}\]

The procedure does the same thing bit by bit (\(13 = 1101_2\), read from the right):

\(e\) lowest bit base before result after base after squaring

13

1

7

\(1 \cdot 7 = 7\)

\(49 \equiv 5\)

6

0

5

7 (unchanged)

\(25 \equiv 3\)

3

1

3

\(7 \cdot 3 = 21 \equiv 10\)

\(9\)

1

1

9

\(10 \cdot 9 = 90 \equiv 2\)

\(81 \equiv 4\)

0

—

2

Cross-check with Fermat: \(7^{10} \equiv 1\), so \(7^{13} \equiv 7^3 = 343 = 31 \cdot 11 + 2 \equiv 2\). Correct.

def power_mod(base, exp, m):
    """Compute base**exp % m by repeated squaring."""
    result = 1
    base %= m
    while exp > 0:
        if exp & 1:                  # lowest bit of exp is 1
            result = result * base % m
        base = base * base % m       # square for the next bit
        exp >>= 1                    # shift to the next bit
    return result

print(power_mod(7, 13, 11), power_mod(13, 27, 55), power_mod(2790, 2753, 3233))
print(pow(7, 13, 11))   # the built-in three-argument pow agrees
2 7 65
2

23.10.4. Choosing a method

  • Small exponent, prime modulus, base not a multiple of it: reduce the exponent with Fermat first (mod \(p - 1\)), then finish by hand.

  • Anything in code: the built-in pow(a, e, m) (Python), BigInteger.modPow (Java), or a constant-time library routine for cryptography.

  • Never compute a ** e % m with a large e. It builds the gigantic integer first.

Timing leaks

The textbook procedure does extra work exactly when a bit of the exponent is 1. If the exponent is a secret key, an attacker who can time or power-measure your device can read the bits off one by one. Paul Kocher demonstrated this in 1996. Cryptographic libraries use constant-time variants such as the "Montgomery ladder", which do the same operations whatever the bits are. Use your own power_mod for learning, never for real keys.

Computer-science connection: the same trick everywhere

Square-and-multiply works for any associative operation, not just modular multiplication. It computes Fibonacci numbers in \(O(\log n)\) steps by raising a \(2 \times 2\) matrix to the \(n\)th power (Chapter 27). It counts paths of length \(k\) in a graph using adjacency-matrix powers (Chapter 25), and it composes a permutation with itself \(k\) times. Recognising "this is exponentiation in disguise" is a classic algorithm-interview move.

Exponentiation race

Let the user enter \(a\), \(e\) and \(m\). Show the exponent in binary, then animate the square-and-multiply table, lighting each bit as it is consumed. Beside it, run naive repeated multiplication and keep a step counter. Push \(e\) to \(10^{6}\) and then \(10^{18}\) to feel the difference between linear and logarithmic.

23.10.5. Exercises

  1. Compute \(2^{100} \bmod 7\) using Fermat’s little theorem.

  2. What is the last digit of \(3^{2026}\)? (Find the cycle of powers of 3 mod 10.)

  3. Compute \(5^{23} \bmod 13\) with square-and-multiply, showing the table.

  4. Find \(11^{-1} \pmod{26}\), and use it to solve \(11x \equiv 4 \pmod{26}\).

  5. Solve \(4x \equiv 6 \pmod{10}\) and explain why \(6x \equiv 4 \pmod 9\) has no solution.

  6. In C, what does -17 % 5 give, and in Python? Write an expression that gives Python’s answer in C. Try it: −17 % 5 in each language.

  7. Show that the square of any integer is congruent to 0 or 1 mod 4. Deduce that no integer of the form \(4k + 3\) is a sum of two squares.

Answers
  1. \(2^3 = 8 \equiv 1 \pmod 7\), which is even better than Fermat’s \(2^6\). \(100 = 33 \cdot 3 + 1\), so \(2^{100} \equiv 2^1 = 2\). Using Fermat (\(2^6 \equiv 1\), \(100 = 16\cdot6 + 4\)): \(2^4 = 16 \equiv 2\). Same answer.

  2. Powers of 3 mod 10 cycle \(3, 9, 7, 1\) with period 4. \(2026 = 506 \cdot 4 + 2\), so the last digit is the second in the cycle, 9.

  3. \(23 = 10111_2 = 16 + 4 + 2 + 1\). Squares mod 13: \(5^1 = 5\), \(5^2 = 25 \equiv 12\), \(5^4 \equiv 144 \equiv 1\), \(5^8 \equiv 1\), \(5^{16} \equiv 1\). Product: \(1 \cdot 1 \cdot 12 \cdot 5 = 60 \equiv 8\). So \(5^{23} \equiv 8 \pmod{13}\). (Check with Fermat: \(5^{12}\equiv1\), so \(5^{23} \equiv 5^{11} = 5^8\cdot5^2\cdot5 \equiv 1\cdot12\cdot5 \equiv 8\).)

  4. \(26 = 2\cdot11 + 4\), \(11 = 2\cdot4 + 3\), \(4 = 1\cdot3 + 1\). Back-substitute: \(1 = 4 - 3 = 4 - (11 - 2\cdot4) = 3\cdot4 - 11 = 3(26 - 2\cdot11) - 11 = 3\cdot26 - 7\cdot11\). So \(11^{-1} \equiv -7 \equiv 19\). Check: \(11\cdot19 = 209 = 8\cdot26 + 1\). Then \(x \equiv 19 \cdot 4 = 76 \equiv 76 - 52 = 24\). Check: \(11 \cdot 24 = 264 = 10\cdot26 + 4\).

  5. As in the text, \(x \equiv 4 \pmod 5\), i.e. \(x \in \{4, 9\} \pmod{10}\). For \(6x \equiv 4 \pmod 9\), \(\gcd(6, 9) = 3\) does not divide 4. Every \(6x - 9y\) is a multiple of 3, so it can never equal 4.

  6. In C, -17 / 5 == -3 and -17 % 5 == -2. In Python, -17 // 5 == -4 and -17 % 5 == 3. Portable C: ((-17 % 5) + 5) % 5, which gives 3.

  7. Every integer is \(\equiv 0, 1, 2, 3 \pmod 4\), and the squares are \(0, 1, 4 \equiv 0, 9 \equiv 1\). So a sum of two squares is \(\equiv 0 + 0, 0 + 1\) or \(1 + 1\), i.e. 0, 1 or 2 mod 4, and never 3.

23.11. Applications: hashing, check digits, and pseudo-random numbers

23.11.1. Hashing: mod as a bucket chooser

A hash table with \(m\) buckets stores key \(k\) in bucket \(h(k) \bmod m\), where \(h\) scrambles the key into a big integer. The remainder lands in \(0 \ldots m-1\) (if you use floor-mod!) and spreads keys around, provided the keys don’t share structure with \(m\).

keys = [0, 8, 16, 24, 32, 40, 48, 56]      # e.g. aligned addresses
for m in (8, 7):
    print(m, sorted(k % m for k in keys))
8 [0, 0, 0, 0, 0, 0, 0, 0]
7 [0, 0, 1, 2, 3, 4, 5, 6]

Keys that are all multiples of 8 collide completely in 8 buckets, but spread out across 7. In general, the keys \(k, k + s, k + 2s, \ldots\) hit only \(m / \gcd(s, m)\) distinct buckets. A prime \(m\) shares no factor with any stride smaller than itself. That is the classical case for prime table sizes. Modern tables (Python’s dict, Java’s HashMap, Rust’s HashMap) use power-of-two sizes for speed (& (m - 1) instead of division) and compensate by mixing the hash bits thoroughly first. Java’s HashMap XORs the high half of the hash into the low half before masking.

Hash functions themselves are modular arithmetic. Java’s String.hashCode is

\[h = s_0 \cdot 31^{n-1} + s_1 \cdot 31^{n-2} + \cdots + s_{n-1} \pmod{2^{32}},\]

computed by Horner’s rule (\(h \leftarrow 31h + s_i\)), with the mod coming free from 32-bit overflow. For "hi" it gives \(104 \cdot 31 + 105 = 3329\). The Rabin–Karp substring search uses the same polynomial hash mod a large prime. Sliding the window by one character updates the hash in constant time: subtract the old leading character’s term, multiply by the base, add the new character.

23.11.2. Check digits: catching typos with a remainder

A check digit is one extra digit chosen so that some modular sum comes out to 0. Typing errors break the sum.

ISBN-10 uses weights 10 down to 1 and requires

\[10 d_1 + 9 d_2 + 8 d_3 + \cdots + 2 d_9 + 1 \cdot d_{10} \equiv 0 \pmod{11},\]

where a check value of 10 is written X. Worked example: 0-306-40615-2. Try it: Check the ISBN-10 example.

\[\begin{aligned} &10\cdot0 + 9\cdot3 + 8\cdot0 + 7\cdot6 + 6\cdot4 + 5\cdot0 + 4\cdot6 + 3\cdot1 + 2\cdot5 + 1\cdot2\\ &= 0 + 27 + 0 + 42 + 24 + 0 + 24 + 3 + 10 + 2 = 132 = 12 \cdot 11 \equiv 0 \pmod{11}. \quad\checkmark \end{aligned}\]

Why 11 and not 10? Because 11 is prime. A single wrong digit changes the sum by \(w \cdot (\text{error})\), where both factors are nonzero and less than 11, so by Euclid’s lemma 11 can’t divide the change. Swapping adjacent digits \(x, y\) changes the sum by \(\pm(x - y)\), again not a multiple of 11 unless \(x = y\). So every single-digit error and every adjacent swap is caught. (ISBN-13 switched to weights 1, 3, 1, 3, …​ mod 10, which misses a few swaps, for compatibility with retail barcodes.)

The Luhn algorithm protects credit-card and IMEI numbers. From the right, double every second digit, and if a doubled value exceeds 9, subtract 9 (which is the same as adding its two digits). The total must be \(\equiv 0 \pmod{10}\).

Example 126. Procedure — Luhn check

Input: a string of digits.

Steps:

  1. Starting from the rightmost digit (position 0), go leftwards.

  2. Keep digits in even positions as they are. Double digits in odd positions, and subtract 9 from any result above 9.

  3. Add everything up.

Output: valid if the total is a multiple of 10.

Worked example: 7992 7398 713. Reading from the right, the digits are 3, 1, 7, 8, 9, 3, 7, 2, 9, 9, 7. The odd positions (1, 8, 3, 2, 9) are doubled to 2, 16, 6, 4, 18, which become 2, 7, 6, 4, 9 after subtracting 9 where needed. Even positions (3, 7, 9, 7, 9, 7) stay as they are. Try it: Check the Luhn example.

\[(3 + 7 + 9 + 7 + 9 + 7) + (2 + 7 + 6 + 4 + 9) = 42 + 28 = 70 \equiv 0 \pmod{10}. \quad\checkmark\]
def luhn_valid(number: str) -> bool:
    digits = [int(c) for c in number if c.isdigit()]
    total = 0
    for i, d in enumerate(reversed(digits)):
        if i % 2 == 1:          # every second digit from the right
            d *= 2
            if d > 9:
                d -= 9          # same as adding the two digits of d
        total += d
    return total % 10 == 0

def isbn10_valid(isbn: str) -> bool:
    chars = [c for c in isbn if c.isdigit() or c in "Xx"]
    values = [10 if c in "Xx" else int(c) for c in chars]
    return sum((10 - i) * v for i, v in enumerate(values)) % 11 == 0

print(luhn_valid("7992 7398 713"), luhn_valid("7992 7398 731"))
print(isbn10_valid("0-306-40615-2"), isbn10_valid("0-306-46015-2"))
True False
True False
Check digits are not security

Check digits detect accidents, not attacks. Anyone can compute a valid Luhn digit for a made-up number. Luhn also misses the adjacent swap \(09 \leftrightarrow 90\), since both pairs contribute 9. For tamper resistance you need a cryptographic MAC or signature. For bulk data (network packets, files) you need stronger codes such as CRCs, which are polynomial remainders mod 2, or checksums like Adler-32, which is two running sums mod 65521, a prime.

23.11.3. Pseudo-random numbers: the linear congruential generator

A computer is deterministic, yet simulations, games and randomised algorithms need numbers that look random. The oldest workable trick is the linear congruential generator (LCG):

\[x_{n+1} = (a\, x_n + c) \bmod m.\]

Pick a seed \(x_0\) and iterate. There are only \(m\) possible states, so the sequence must eventually cycle. A well-chosen LCG cycles through all \(m\) values before repeating.

Worked example: \(a = 5\), \(c = 3\), \(m = 16\), seed \(x_0 = 7\). Try it: Trace the LCG’s 16 states.

\[\begin{aligned} x_1 &= (5\cdot7 + 3) \bmod 16 = 38 \bmod 16 = 6\\ x_2 &= (5\cdot6 + 3) \bmod 16 = 33 \bmod 16 = 1\\ x_3 &= (5\cdot1 + 3) \bmod 16 = 8\\ x_4 &= (5\cdot8 + 3) \bmod 16 = 43 \bmod 16 = 11\\ &\ \,\vdots \end{aligned}\]
def lcg(seed, a=5, c=3, m=16):
    x = seed
    while True:
        x = (a * x + c) % m
        yield x

gen = lcg(7)
print([next(gen) for _ in range(17)])
[6, 1, 8, 11, 10, 5, 12, 15, 14, 9, 0, 3, 2, 13, 4, 7, 6]

All 16 values appear before 7 recurs and the cycle restarts at 6. This is no accident. The Hull–Dobell theorem says an LCG has full period \(m\) exactly when \(\gcd(c, m) = 1\), \(a - 1\) is divisible by every prime factor of \(m\), and \(a - 1\) is divisible by 4 if \(m\) is. Here \(c = 3\) is coprime to 16 and \(a - 1 = 4\) is divisible by both 2 and 4.

Sixteen numbered nodes on a circle connected by arrows in LCG order, alternately coloured for odd and even
Figure 210. The LCG \(x \mapsto (5x + 3) \bmod 16\) visits all 16 states in one cycle. Notice the colours: odd and even simply alternate.
LCG low bits are not random

Look at the diagram: the outputs alternate odd, even, odd, even. With \(m = 2^k\), the lowest bit of an LCG has period 2, the lowest two bits have period 4, and so on. Write rand() % 2 for a coin flip on such a generator and you get perfectly alternating "random" coins. Old C library rand() implementations did exactly this. Use the high bits, or better, a modern generator. Python’s random uses the Mersenne Twister. NumPy defaults to PCG64, which is an LCG whose output is scrambled before use. Never use any of these for passwords, tokens or keys. Use secrets (Python) or the OS’s cryptographic generator. An attacker who sees a few LCG outputs can recover the parameters and predict everything that follows.

RANDU

IBM’s RANDU, \(x_{n+1} = 65539\, x_n \bmod 2^{31}\), was used throughout the 1960s and 70s. Since \(65539 = 2^{16} + 3\), every output satisfies \(x_{n+2} = 6x_{n+1} - 9x_n \pmod{2^{31}}\). Plot consecutive triples in 3D and they all fall on just 15 parallel planes. Donald Knuth called it "really horrible". Many published simulation results from that era had to be re-examined.

Period explorer

Sliders for \(a\), \(c\), \(m\) and the seed. Draw the state graph as in the figure, so that cycles and tails become visible, and report the period. Let the reader test the Hull–Dobell conditions by breaking them one at a time (for example, set \(c = 4\) with \(m = 16\)). A second panel plots consecutive pairs \((x_n, x_{n+1})\) so the lattice structure of LCGs becomes visible.

23.12. Cryptography: Diffie–Hellman and RSA

23.12.1. The problem

You want to send your card number to a shop you’ve never contacted, over a network where anyone can read every byte. Classical ciphers need a shared secret key. How do you agree on one when every message is public? Before 1976 almost everyone assumed this was impossible. Number theory says otherwise.

23.12.2. Diffie–Hellman: agreeing on a secret in public

The idea needs only modular powers and one observation: \((g^a)^b = g^{ab} = (g^b)^a\).

  1. Alice and Bob publicly agree on a prime \(p\) and a base \(g\).

  2. Alice picks a secret \(a\) and sends \(A = g^a \bmod p\). Bob picks a secret \(b\) and sends \(B = g^b \bmod p\).

  3. Alice computes \(B^a \bmod p\) and Bob computes \(A^b \bmod p\). Both equal \(g^{ab} \bmod p\), which is their shared secret.

Worked example with \(p = 23\), \(g = 5\), Alice’s \(a = 6\), Bob’s \(b = 15\). The repeated squares of 5 mod 23 are Try it: Diffie–Hellman with an eavesdropper; Compute 5⁶ mod 23.

\[5^1 \equiv 5,\quad 5^2 = 25 \equiv 2,\quad 5^4 \equiv 2^2 = 4,\quad 5^8 \equiv 4^2 = 16.\]
\[\begin{aligned} A &= 5^6 = 5^4 \cdot 5^2 \equiv 4 \cdot 2 = 8 \pmod{23}\\ B &= 5^{15} = 5^8 \cdot 5^4 \cdot 5^2 \cdot 5^1 \equiv 16 \cdot 4 \cdot 2 \cdot 5 = 640 = 27 \cdot 23 + 19 \equiv 19\\[4pt] \text{Alice: } B^a &= 19^6 \equiv (-4)^6 = 4096 = 178 \cdot 23 + 2 \equiv 2\\ \text{Bob: } A^b &= 8^{15} = 2^{45} = (2^{11})^4 \cdot 2 \equiv 1^4 \cdot 2 = 2 &&(2^{11} = 2048 = 89\cdot 23 + 1) \end{aligned}\]

Both arrive at the shared secret 2. An eavesdropper sees \(p = 23\), \(g = 5\), \(A = 8\) and \(B = 19\). To get the secret they must recover \(a\) from \(5^a \equiv 8\). That is the discrete logarithm problem. It’s trivial for \(p = 23\) (try all 22 exponents) but believed infeasible when \(p\) has 600+ digits, even though computing \(g^a\) is fast. Modern TLS usually does the same dance on an elliptic curve instead of with integers mod \(p\).

p, g = 23, 5                 # public: prime modulus and generator
a, b = 6, 15                 # private: Alice's and Bob's secrets
A = pow(g, a, p)             # Alice sends A
B = pow(g, b, p)             # Bob sends B
print(A, B, pow(B, a, p), pow(A, b, p))
8 19 2 2
Paint-mixing intuition

The usual analogy: mixing paint is easy, but un-mixing it is practically impossible. Both parties start with a public colour and add their own secret colour. They swap the mixtures in public, and each adds their secret colour again. They end up with the same three-colour mix, which nobody watching can reproduce. Diffie and Hellman published in 1976. It later emerged that GCHQ’s Malcolm Williamson had found the same scheme around 1974, and that Clifford Cocks had found RSA in 1973, but both were classified.

23.12.3. RSA: a lock anyone can close but only you can open

Diffie–Hellman agrees on a key. RSA (Rivest, Shamir, Adleman, 1977) goes further: a public key that anyone can use to encrypt a message to you, and a private key that only you can use to decrypt. It rests on everything in this chapter:

  • Primes and factoring (Section 23.2): the public modulus is \(n = pq\), and nobody can factor it.

  • Euler’s theorem (Section 23.9): raising to the power \(1 + k\varphi(n)\) gets you back where you started.

  • Modular inverses via extended Euclid (Section 23.8): to build the private key.

  • Fast exponentiation (Section 23.10): to encrypt and decrypt efficiently.

Example 127. Procedure — RSA

Key generation (done once by the receiver):

  1. Choose two distinct primes \(p\) and \(q\). Compute \(n = pq\) and \(\varphi = (p - 1)(q - 1)\).

  2. Choose a public exponent \(e\) with \(1 < e < \varphi\) and \(\gcd(e, \varphi) = 1\).

  3. Compute the private exponent \(d = e^{-1} \bmod \varphi\) by extended Euclid.

  4. Publish \((n, e)\). Keep \(d\) secret, and destroy \(p\), \(q\) and \(\varphi\).

Encryption (anyone): the message is a number \(0 \le M < n\). Send \(C = M^e \bmod n\).

Decryption (receiver): compute \(M = C^d \bmod n\).

23.12.4. Worked example: RSA with tiny numbers, every step shown

Step 1: primes. \(p = 5\) and \(q = 11\). Then Try it: Tiny RSA, every step; Find d = 3⁻¹ mod 40.

\[n = 5 \cdot 11 = 55, \qquad \varphi = (5 - 1)(11 - 1) = 4 \cdot 10 = 40.\]

Step 2: public exponent. Try \(e = 3\). Since \(40 = 13 \cdot 3 + 1\), we have \(\gcd(40, 3) = \gcd(3, 1) = 1\), so \(e = 3\) is allowed.

Step 3: private exponent. We need \(3d \equiv 1 \pmod{40}\). The Euclid line \(40 = 13 \cdot 3 + 1\) rearranges to

\[1 = 40 - 13 \cdot 3 \quad\Rightarrow\quad 3 \cdot (-13) \equiv 1 \pmod{40} \quad\Rightarrow\quad d \equiv -13 \equiv 27 \pmod{40}.\]

Check: \(3 \cdot 27 = 81 = 2 \cdot 40 + 1\). Correct. The public key is \((n, e) = (55, 3)\) and the private key is \(d = 27\).

Step 4: encrypt the message \(M = 7\):

\[C = 7^3 \bmod 55 = 343 \bmod 55 = 343 - 6 \cdot 55 = 343 - 330 = 13.\]

Step 5: decrypt \(C = 13\) by computing \(13^{27} \bmod 55\) with square-and-multiply. In binary \(27 = 11011_2 = 16 + 8 + 2 + 1\). The squares are Try it: Decrypt 13²⁷ mod 55.

\[\begin{aligned} 13^1 &\equiv 13\\ 13^2 &= 169 = 3 \cdot 55 + 4 \equiv 4\\ 13^4 &\equiv 4^2 = 16\\ 13^8 &\equiv 16^2 = 256 = 4 \cdot 55 + 36 \equiv 36\\ 13^{16} &\equiv 36^2 = 1296 = 23 \cdot 55 + 31 \equiv 31 \end{aligned}\]

and multiplying the ones we need gives

\[\begin{aligned} 13^{27} &= 13^{16} \cdot 13^{8} \cdot 13^{2} \cdot 13^{1}\\ &\equiv 31 \cdot 36 \cdot 4 \cdot 13\\ &= 1116 \cdot 4 \cdot 13 \equiv 16 \cdot 4 \cdot 13 &&(1116 = 20 \cdot 55 + 16)\\ &= 64 \cdot 13 \equiv 9 \cdot 13 &&(64 = 55 + 9)\\ &= 117 \equiv 7 \pmod{55} &&(117 = 2 \cdot 55 + 7). \end{aligned}\]

The receiver recovers \(M = 7\).

23.12.5. Why RSA works

Because \(ed \equiv 1 \pmod{\varphi}\), we have \(ed = 1 + k\varphi\) for some integer \(k\). In the example, \(3 \cdot 27 = 81 = 1 + 2 \cdot 40\). If \(\gcd(M, n) = 1\), Euler’s theorem gives

\[\begin{aligned} C^d &\equiv (M^e)^d = M^{ed} &&\text{(definition of } C\text{)}\\ &= M^{1 + k\varphi} = M \cdot \left(M^{\varphi}\right)^k &&\text{(exponent laws)}\\ &\equiv M \cdot 1^k = M \pmod n &&\text{(Euler: } M^{\varphi(n)} \equiv 1). \end{aligned}\]

(If \(M\) happens to share a factor with \(n\), the result still holds. Applying Fermat separately mod \(p\) and mod \(q\) and combining with the Chinese remainder theorem shows it.)

Why it’s secure. An attacker knows \(n\) and \(e\). To find \(d\) they need \(\varphi = (p-1)(q-1)\), and getting that from \(n\) is as hard as factoring \(n\). With \(n = 55\), factoring takes a second. Real keys use primes of 1,024+ bits each, giving a 617-digit \(n\), and the best known algorithms would take far longer than the age of the universe.

The same arithmetic at the size of a classic textbook example: Try it: RSA with 61 and 53.

p, q = 61, 53
n = p * q                    # public modulus
phi = (p - 1) * (q - 1)      # Euler's totient of n
e = 17                       # public exponent, gcd(e, phi) == 1
d = pow(e, -1, phi)          # private exponent: e*d = 1 (mod phi)
print(f"n={n} phi={phi} e={e} d={d} check={(e * d) % phi}")

m = 65                       # the message, 0 <= m < n
c = pow(m, e, n)             # encrypt with the public key (n, e)
back = pow(c, d, n)          # decrypt with the private key d
print(f"m={m} c={c} decrypted={back}")
n=3233 phi=3120 e=17 d=2753 check=1
m=65 c=2790 decrypted=65
Textbook RSA is not real RSA

What we just did, "textbook RSA", is insecure as written. It is deterministic: the same message always gives the same ciphertext, so an attacker can encrypt guesses and compare. Small messages with small \(e\) can be recovered by an ordinary integer root: if \(M^3 < n\), then \(C = M^3\) exactly. Ciphertexts can also be multiplied to forge related ones. Real systems pad the message with randomness (OAEP), use \(e = 65537\), generate primes with vetted libraries, and today mostly use RSA only for signatures or not at all, preferring elliptic curves. Learn the mathematics here, and use a library such as cryptography or libsodium for anything real.

Computer-science connection: what a quantum computer would break

Shor’s algorithm (1994) would let a large, error-corrected quantum computer factor \(n\) and compute discrete logarithms efficiently. That would break both RSA and Diffie–Hellman (including the elliptic-curve versions). In 2024 NIST standardised post-quantum replacements (ML-KEM, from Kyber, and ML-DSA, from Dilithium). They are built on lattice problems: linear algebra mod \(q\) with deliberately added noise. The modulus never goes away.

RSA playground

Let the reader pick small primes \(p, q\) and an \(e\). Show \(\gcd(e, \varphi)\) by Euclid, flag an invalid \(e\), and derive \(d\) with the extended-Euclid table on screen. Encrypt a short word letter by letter (and show why that is a terrible idea: identical letters give identical ciphertexts). Finally, an "attacker" pane factors \(n\) by trial division and shows the time growing as \(p\) and \(q\) get bigger.

US curriculum

Modular arithmetic is not a standard topic in the US high-school sequence (Algebra I, Geometry, Algebra II, Precalculus). Students meet it through the % operator in AP Computer Science A / Principles, through math competitions (MATHCOUNTS, AMC 10/12, where it is essential), and in some Discrete Mathematics or cryptography electives. The rigorous treatment (congruences, Fermat, RSA) is standard in a first-year college Discrete Mathematics course and in Elementary Number Theory.

23.13. Interactive tools

Browser tools on the companion website that go with this chapter. Each example link in the chapter opens one of them with that example already set up.

23.14. Mastery check

  1. Use the Euclidean algorithm to find \(\gcd(391, 299)\), showing each division. Then express it as \(391x + 299y\).

  2. Find \(\operatorname{lcm}(391, 299)\).

  3. Find \(11^{-1} \pmod{26}\) and verify it. Does \(13\) have an inverse mod 26? Why or why not?

  4. Compute \(5^{100} \bmod 13\) using Fermat’s little theorem.

  5. Compute \(3^{45} \bmod 17\) using square-and-multiply.

  6. In Python, -17 // 5 and -17 % 5 give what? In C or Java? Which one is consistent with \(0 \le r < m\)?

  7. Toy RSA: \(p = 3\), \(q = 11\), \(e = 3\). Find \(n\), \(\varphi\) and \(d\). Encrypt \(M = 4\), then decrypt your ciphertext and confirm you get 4 back.

  8. Is 0-19-853453-1 a valid ISBN-10? Show the weighted sum.

Decision rule: All correct without hesitation → move on to Chapter 24. Stuck on 1–3 → reread Section 23.4, Section 23.5 and Section 23.8. Stuck on 4, 5 or 7 → reread Section 23.9, Section 23.10 and Section 23.12. Stuck on more than three → work the section exercises before continuing.

Mastery check answers
  1. \(391 = 1 \cdot 299 + 92\), \(299 = 3 \cdot 92 + 23\), \(92 = 4 \cdot 23 + 0\). So the GCD is 23. Back-substitute: \(23 = 299 - 3 \cdot 92 = 299 - 3(391 - 299) = 4 \cdot 299 - 3 \cdot 391\), giving \(x = -3, y = 4\). Check: \(1196 - 1173 = 23\).

  2. \(391 \cdot 299 / 23 = 17 \cdot 299 = 5083\). (Indeed \(391 = 17 \cdot 23\) and \(299 = 13 \cdot 23\), so the LCM is \(13 \cdot 17 \cdot 23 = 5083\).)

  3. From \(1 = 3 \cdot 26 - 7 \cdot 11\) (see the exercises), \(11^{-1} \equiv -7 \equiv 19\). Check: \(11 \cdot 19 = 209 = 8 \cdot 26 + 1\). 13 has no inverse mod 26 because \(\gcd(13, 26) = 13 \ne 1\). Every multiple of 13 is \(\equiv 0\) or \(13 \pmod{26}\), never 1.

  4. \(5^{12} \equiv 1 \pmod{13}\) and \(100 = 8 \cdot 12 + 4\), so \(5^{100} \equiv 5^4\). \(5^2 = 25 \equiv -1\), so \(5^4 \equiv 1\). The answer is 1.

  5. \(45 = 101101_2 = 32 + 8 + 4 + 1\). Squares mod 17: \(3^1 = 3\), \(3^2 = 9\), \(3^4 = 81 \equiv 13\), \(3^8 \equiv 169 \equiv 16\), \(3^{16} \equiv 256 \equiv 1\), \(3^{32} \equiv 1\). Product: \(1 \cdot 16 \cdot 13 \cdot 3 = 624 = 36 \cdot 17 + 12\). The answer is 12. (Fermat check: \(3^{16} \equiv 1\), so \(3^{45} \equiv 3^{13} = 3^8 \cdot 3^4 \cdot 3 \equiv 16\cdot13\cdot3 \equiv 12\).)

  6. Python: \(-4\) and \(3\) (floor division). C/Java: \(-3\) and \(-2\) (truncation). Python’s remainder 3 lies in \(0 \le r < 5\). Both satisfy \(-17 = 5q + r\).

  7. \(n = 33\) and \(\varphi = 2 \cdot 10 = 20\). \(\gcd(3, 20) = 1\). \(3d \equiv 1 \pmod{20}\) gives \(d = 7\) (\(21 = 20 + 1\)). Encrypt: \(4^3 = 64 = 33 + 31\), so \(C = 31\). Decrypt: \(31 \equiv -2 \pmod{33}\), so \(31^7 \equiv (-2)^7 = -128 \equiv -128 + 4 \cdot 33 = 4\). Correct.

  8. \(10\cdot0 + 9\cdot1 + 8\cdot9 + 7\cdot8 + 6\cdot5 + 5\cdot3 + 4\cdot4 + 3\cdot5 + 2\cdot3 + 1\cdot1 = 0 + 9 + 72 + 56 + 30 + 15 + 16 + 15 + 6 + 1 = 220 = 20 \cdot 11\). That is \(\equiv 0 \pmod{11}\), so the ISBN is valid.