Monocurl Essays
Series Download

Cantor's diagonal argument: some infinities are bigger

Sizes of infinite sets are compared by pairing. The integers and the fractions pair off with the counting numbers, and the real numbers provably do not.

23 min·High school and early college·

AssumesProof by contradiction: why √2 is not a fractionSets, Venn diagrams and inclusion-exclusion

Each counting number $n$ is joined to its double $2n$. Every even number receives exactly one line, so the even numbers, which look like half of the counting numbers, pair off with all of them.
Monocurl source
let bx = |m| -3.52 + m * 0.44
let TOP = 1.05
let BOT = -0.95
let Links = |k| block {
    for (n in range(1, 9)) {
        let f = clamp(0, k - (n - 1), 1)
        if (f > 0.03) {
            . Seg([bx(2 * n), TOP - 0.3, 0], [bx(2 * n), lerp(TOP - 0.3, BOT + 0.3, f), 0], INK, 3)
        }
    }
}
mesh links = Links(k: 0)
mesh rows = [
    map(range(1, 9), |n| NumTile([bx(2 * n), TOP, 0], to_string(n), EMBER, 0.5, 0.5, 0.8)),
    map(range(1, 17), |m| NumTile([bx(m), BOT, 0], to_string(m), [MIST, AZURE][to_int(mod(m, 2) == 0)], 0.38, 0.5, 0.7, [0, 0.2][to_int(mod(m, 2) == 0)])),
    center{[-2.0, 1.75, 0]} Cap("every counting number n", 0.8, EMBER),
    center{[-2.1, -1.7, 0]} Cap("the even number 2n", 0.8, AZURE)
]

slide "pair"
    play Wait(0.6)
    links.k = 8
    play Lerp(5, [&links], linear)
    play Wait(2.2)

Uses the shared definitions for this lesson's figures.

Are there more counting numbers $1, 2, 3, \dots$ than even numbers $2, 4, 6, \dots$? The obvious answer is yes, twice as many, since the even numbers leave out every other one. But join each number $n$ to its double $2n$, as in the animation. Every counting number gets a partner, every even number gets a partner, and nobody is used twice. If two crowds can be lined up one against one with nobody left over, it is hard to maintain that one crowd is bigger.

So two reasonable ways of comparing sizes disagree. The same conflict, with the square numbers $1, 4, 9, \dots$ in place of the even ones, puzzled Galileo, who concluded that “equal”, “greater” and “less” do not apply to infinite collections. In the 1870s Georg Cantor took the other way out: he chose one of the two ways, followed it strictly, and found that infinite sets do come in different sizes.

Notation: $\mathbb{N} = \{1, 2, 3, \dots\}$ is the set of counting numbers, $\mathbb{Z}$ the integers, $\mathbb{Q}$ the rational numbers (fractions $\frac{p}{q}$ of integers with $q \neq 0$) and $\mathbb{R}$ the real numbers. From the lesson on sets we use $\in$ and $\subseteq$, and from proof by contradiction the method of assuming the opposite and deriving an impossibility.

Size without counting

To check that a hall has as many chairs as people without counting either, ask everyone to sit. If no chair is empty and nobody is standing, the numbers agree. For finite sets this test and ordinary counting always give the same verdict; indeed counting is this test, a pairing of the objects with $1, 2, \dots, n$. The test has the advantage that it still makes sense when no number $n$ is available.

In the hall, $f$ sends each person to a chair. Injective says no chair holds two people, and surjective says no chair is empty.

The rival test, “a part is smaller than the whole”, is also correct for finite sets: a finite set cannot be paired off with a proper part of itself, which is the pigeonhole principle. For infinite sets the two tests conflict, as the opening showed, and we keep the pairing test. The first theorem records what the animation drew.

Hilbert’s hotel

David Hilbert dramatized this with a hotel that has one room for each counting number, all occupied. A new guest arrives.

Hilbert’s hotel. Every room is occupied, and a new guest arrives. Each guest moves from room $n$ to room $n + 1$, which empties room 1 without sending anyone away. The row of rooms continues past the right edge of the picture.
Monocurl source
let rx = |i| -3.3 + (i - 1) * 0.72
let RYH = 0.1
# rooms and guests thin out past room 9, where the row leaves the picture
let vis = |x| clamp(0, (rx(10) + 0.4 - x) / 1.12, 1)
let wa = |col, a| [col[0], col[1], col[2], a]
let Guest = |pos, txt, col, a = 1| [
    center{pos} fill{wa(tint(col, 0.3), a)} stroke{wa(col, a), 2.5} Circle(0.27, 96),
    center{pos} Math(txt, 0.72, wa(col, a))
]
let Move = |t| block {
    let u = clamp(0, t, 1)
    for (n in range(1, 11)) {
        let x = rx(n) + u * 0.72
        if (vis(x) > 0.02) {
            . Guest([x, RYH, 0], to_string(n), AZURE, vis(x))
        }
    }
    let v = clamp(0, t - 1, 1)
    . Guest([rx(1), lerp(1.5, RYH, v), 0], "\ast", LEAF)
}
mesh rooms = [
    map(range(1, 10), |i| Box([rx(i), RYH, 0], [0.64, 1.0], SLATE, 0.06, 2.5)),
    center{[rx(10), RYH, 0]} fill{wa(tint(SLATE, 0.06), 0.35)} stroke{wa(SLATE, 0.35), 2.5} Rect([0.64, 1.0]),
    map(range(1, 10), |i| center{[rx(i), RYH - 0.82, 0]} Math(to_string(i), 0.78, SLATE)),
    center{[rx(10), RYH - 0.82, 0]} Math("10", 0.78, wa(SLATE, 0.4)),
    center{[-2.0, 1.5, 0]} Cap("a new guest", 0.8, LEAF),
    center{[2.9, 1.5, 0]} Cap("and so on", 0.76, SLATE)
]
mesh guests = Move(t: 0)
mesh words = [center{[0, -1.6, 0]} Cap("every room is taken", 0.85, ROSE)]

slide "shift"
    play Wait(1)
    words = []
    play Fade(0.3, [&words])
    guests.t = 1
    play Lerp(2.2, [&guests])
    words = [center{[0, -1.6, 0]} Math("\text{the guest in room } n \text{ moves to room } n + 1", 0.82, AZURE)]
    play Fade(0.4, [&words])
    guests.t = 2
    play Lerp(1.4, [&guests])
    play Wait(2.2)

Uses the shared definitions for this lesson's figures.

No finite hotel can do this. Here the move $n \mapsto n + 1$ is a bijection from $\mathbb{N}$ to $\{2, 3, 4, \dots\}$, so the full hotel has the same size as itself with a room removed.

Pause and try

Now a bus arrives with infinitely many new guests, in seats numbered $1, 2, 3, \dots$, and the hotel is full. Find new rooms for everybody. (Moving each guest “infinitely many rooms along” is not an instruction anyone can follow.)

Show answerHide answer

Send the guest in room $n$ to room $2n$, and the passenger in seat $k$ to room $2k - 1$. The old guests fill the even rooms, once each, and the passengers fill the odd rooms, once each. Every room has exactly one occupant.

Countable sets: the integers

A bijection $f : \mathbb{N} \to S$ is the same thing as a list $f(1), f(2), f(3), \dots$ in which every element of $S$ appears exactly once. So the question “is $S$ the same size as $\mathbb{N}$?” becomes “can the elements of $S$ be written in a list that misses nothing?”

The integers go on forever in both directions, so listing them from left to right is hopeless: there is no leftmost one to start with. Listing all the positive ones first also fails, because then $-1$ would never be reached. A list must reach each element after finitely many steps. The fix is to start in the middle and alternate.

Listing the integers by starting at 0 and swinging outward: $0, 1, -1, 2, -2, \dots$ Every integer is reached after finitely many steps.
Monocurl source
let ix = |v| v * 0.75
let YL = 0.35
let ORDER = [0, 1, -1, 2, -2, 3, -3, 4, -4]
let Swing = |i, f| {
    let a = ORDER[i]
    let b = ORDER[i + 1]
    let up = [1, -1][mod(i, 2)]
    let c = (ix(a) + ix(b)) / 2
    let r = (ix(a) - ix(b)) / 2
    let h = 0.2 + 0.13 * abs(a - b)
    let n = to_int(max(2, ceil(30 * f)))
    return Path(map(sample(0, PI * f, n), |t| [c + r * cos(t), YL + up * (0.29 + h * sin(t)), 0]), EMBER, 3.5)
}
let Swings = |k| block {
    for (i in range(0, len(ORDER) - 1)) {
        let f = clamp(0, k - i, 1)
        if (f > 0.03) {
            . Swing(i, f)
        }
    }
}
let Seen = |k| block {
    for (i in range(0, len(ORDER))) {
        if (k >= i - 0.001) {
            . NumTile([ix(ORDER[i]), YL, 0], to_string(ORDER[i]), EMBER, 0.56, 0.5, 0.76, 0.25)
        }
    }
}
let Entry = |i| center{[-2.75 + i * 0.66, -1.7, 0]} Math(to_string(ORDER[i]), 0.9, EMBER)
mesh swings = Swings(k: 0)
mesh tiles = map(range(-4, 5), |v| NumTile([ix(v), YL, 0], to_string(v), SLATE, 0.56, 0.5, 0.76, 0.05))
mesh seen = Seen(k: 0)
mesh listing = [center{[-3.35, -1.7, 0]} Note("list:", 0.78), Entry(0)]

slide "swing"
    play Wait(0.6)
    for (i in range(1, len(ORDER))) {
        swings.k = i
        seen.k = i
        play Lerp(0.75, [&swings, &seen])
        listing .= Entry(i)
        play Fade(0.25, [&listing])
    }
    listing .= center{[-2.75 + len(ORDER) * 0.66, -1.7, 0]} Math("\dots", 0.9, EMBER)
    play Fade(0.3, [&listing])
    play Wait(2)

Uses the shared definitions for this lesson's figures.

The fractions are countable too

The rationals look far more numerous. Between any two of them lies another (their average), so there is no “next” fraction after 0 and they cannot be listed in order of size. Many people expect this to be where countability fails.

The positive fractions can be laid out in a grid, with $\frac{p}{q}$ in column $p$ and row $q$. Reading along the rows fails for the reason that listing the positive integers first failed: the first row never ends. But the grid has another feature. The fractions with $p + q = 2$, then $p + q = 3$, then $p + q = 4$, lie along slanting lines, and each such line is finite.

The positive fractions in a grid, with $p/q$ in column $p$ and row $q$. The walk goes along the diagonals $p + q = 2, 3, 4, \dots$ in turn. A fraction that repeats an earlier value, such as $2/2$, is skipped. Every positive rational is reached.
Monocurl source
let gx = |p| -3.3 + (p - 1) * 0.9
let gy = |q| 1.65 - (q - 1) * 0.66
var walk = []
for (s in range(2, 8)) {
    for (i in range(1, s)) {
        let p = [s - i, i][mod(s, 2)]
        walk .= [p, s - p]
    }
}
let WALK = walk
let kept = |i| to_int(gcd(WALK[i][0], WALK[i][1]) == 1)
let spot = |i| [gx(WALK[i][0]), gy(WALK[i][1]), 0]
let Frac = |p, q, col, amount| NumTile([gx(p), gy(q), 0], str_join([to_string(p), "/", to_string(q)]), col, 0.68, 0.46, 0.74, amount)
let Trail = |k| block {
    for (i in range(0, len(WALK) - 1)) {
        let f = clamp(0, k - i, 1)
        if (f > 0.03) {
            . Seg(spot(i), lerp(spot(i), spot(i + 1), f), EMBER, 4)
        }
    }
}
let Seen = |k| block {
    var listed = 0
    var skipped = 0
    for (i in range(0, len(WALK))) {
        if (k >= i - 0.001) {
            . Frac(WALK[i][0], WALK[i][1], [ROSE, AZURE][kept(i)], [0.05, 0.3][kept(i)])
            listed = listed + kept(i)
            skipped = skipped + 1 - kept(i)
        }
    }
    . center{[2.75, 0.55, 0]} scale{1.4} color{AZURE} Number(listed, 0)
    . center{[2.75, -1.05, 0]} scale{1.4} color{ROSE} Number(skipped, 0)
}
mesh trail = Trail(k: 0)
mesh grid = [
    map(range(1, 7), |p| map(range(1, 7), |q| center{[gx(p), gy(q), 0]} fill{PAPER} stroke{MIST, 2} Rect([0.68, 0.46]))),
    map(range(1, 7), |p| map(range(1, 7), |q| center{[gx(p), gy(q), 0]} Math(str_join([to_string(p), "/", to_string(q)]), 0.74, MIST))),
    center{[2.75, 1.15, 0]} Note("listed", 0.8),
    center{[2.75, -0.45, 0]} Note("skipped", 0.8)
]
mesh seen = Seen(k: 0)

slide "walk"
    play Wait(0.6)
    trail.k = len(WALK) - 1
    seen.k = len(WALK) - 1
    play Lerp(9, [&trail, &seen], linear)
    play Wait(2.2)

Uses the shared definitions for this lesson's figures.

The walk produces the list

$$ \tfrac11,\ \tfrac12,\ \tfrac21,\ \tfrac31,\ \tfrac13,\ \tfrac14,\ \tfrac23,\ \tfrac32,\ \tfrac41,\ \tfrac51,\ \tfrac15,\ \tfrac16,\ \tfrac25,\ \tfrac34,\ \dots $$

with $\frac22$ skipped after $\frac31$ because its value, 1, is already listed.

Pause and try

Where is $\frac{3}{5}$ in this scheme: on which diagonal, and at most how many grid points does the walk visit before it must have reached it?

Show answerHide answer

$\frac35$ has $p + q = 8$, so it is on the diagonal $p + q = 8$, which is the seventh diagonal when $p + q = 2$ is counted as the first. The diagonal $p + q = s$ has $s - 1$ grid points, so the diagonals up to and including $p + q = 8$ hold $1 + 2 + \dots + 7 = 28$ points. The walk reaches $\frac35$ within its first 28 steps.

So the rationals, which are dense on the number line, are no more numerous than the counting numbers. At this point it is reasonable to suspect that every infinite set is countable, and that the definition has only one infinite size to offer.

The real numbers are not countable

Pause and try

Before reading on, commit to a guess. Can the real numbers between 0 and 1 be listed? If you think so, what would your scheme be? If not, how could anyone prove that no scheme works, given how many clever schemes there might be?

Show answerHide answer

They cannot. And the proof does not examine schemes one at a time: it takes an arbitrary list, whatever its origin, and builds from it a number that the list provably omits.

We will describe real numbers by their decimal expansions, and one technical point must be settled first. Some numbers have two expansions: $0.4999\ldots$ (nines forever) and $0.5000\ldots$ are the same number.

Zooming in on 0.5 from the left, by a factor of ten at a time, with ruler marks that rescale with the zoom. The numbers 0.49, 0.499, 0.4999 and so on always sit nine tenths of the way across the window, so the distance from 0.5 to the number with $n$ nines shrinks below every positive bound.
Monocurl source
let LX = -3.0
let W = 6.1
let YZ = 0.15
let NAMES = ["0.4", "0.49", "0.499", "0.4999", "0.49999", "0.499999", "0.4999999", "0.49999999"]
let Zoom = |e| block {
    # a ruler that rescales with the zoom: level j has ticks 1/10^j apart
    for (j in range(1, 9)) {
        let s = 10 ^ (e - j)
        if (s > 0.012 and s < 1.001) {
            for (m in range(1, 10)) {
                let u = 1 - m * s
                if (u > -0.001) {
                    let h = min(0.26, 0.07 + 0.5 * s)
                    . Seg([LX + W * u, YZ - h, 0], [LX + W * u, YZ + h, 0], SLATE, 1.5)
                }
            }
        }
    }
    for (j in range(1, 9)) {
        let u = 1 - 10 ^ (e - j)
        if (u > -0.02 and u < 0.995) {
            . Pt([LX + W * u, YZ, 0], AZURE, 0.13)
        }
        if (u > -0.02 and u < 0.93) {
            . center{[LX + W * u, YZ + 0.75, 0]} Math(NAMES[j - 1], 0.95, AZURE)
        }
    }
    . center{[0.9, -1.55, 0]} scale{1.5} color{INK} Number(10 ^ (e - 1), 0)
}
mesh line = [
    Seg([LX - 0.25, YZ, 0], [LX + W, YZ, 0], SLATE, 2.5),
    Seg([LX + W, YZ - 0.4, 0], [LX + W, YZ + 0.4, 0], ROSE, 4),
    center{[LX + W + 0.05, YZ - 0.8, 0]} Math("0.5", 1.05, ROSE),
    center{[0, 1.75, 0]} Cap("zooming in on 0.5 from the left", 0.85, SLATE),
    center{[-1.0, -1.55, 0]} Note("magnification", 0.85)
]
mesh zoom = Zoom(e: 1)

slide "zoom"
    play Wait(0.8)
    zoom.e = 5
    play Lerp(7, [&zoom], linear)
    play Wait(1.6)

Uses the shared definitions for this lesson's figures.

The expansion $0.4999\ldots$ means the limit of $0.49, 0.499, 0.4999, \dots$, and the number with $n$ nines differs from $0.5$ by exactly $\frac{1}{10^{n+1}}$, which is eventually smaller than any positive number you name. So the limit is $0.5$. (As a geometric series: $0.4 + \frac{9}{100}\left(1 + \frac1{10} + \frac1{100} + \dots\right) = 0.4 + \frac{9}{100} \cdot \frac{10}{9} = 0.5$.) This is the only way a number can have two expansions.

We use the first sentence as a known property of the real numbers. The second can be proved here.

Now take any list of real numbers between 0 and 1. The figure uses a particular list of seven; the method does not care what the list is.

  1. A list of real numbers between 0 and 1, written as decimals. Suppose someone claims that the list, continued forever, contains every such number.
  2. Mark the diagonal: digit 1 of the first number, digit 2 of the second, digit 3 of the third, and so on.
  3. Build a new number x one digit at a time: where the diagonal digit is 5 write 6, and where it is anything else write 5.
  4. x differs from the first number in digit 1, from the second in digit 2, and from the nth number in digit n. So x is nowhere on the list.
The diagonal construction on a list that begins with seven real numbers. The new number $x$ takes its $n$th digit from a rule applied to the $n$th digit of the $n$th number, so it disagrees with every number on the list in at least one digit.
Monocurl source
let NUMS = [0.5, 1 / 3, sqrt(2) - 1, PI - 3, 1 / 7, E - 2, 5 / 9]
let NAMES = ["1/2", "1/3", "\sqrt{2} - 1", "\pi - 3", "1/7", "e - 2", "5/9"]
let digit = |x, k| to_int(mod(floor(x * 10 ^ k + 0.0000001), 10))
let flip = |d| [5, 6][to_int(d == 5)]
let dx = |k| -0.55 + (k - 1) * 0.5
let ry = |i| 1.7 - i * 0.43
let XR = -1.82
let Row = |i| [
    center{[-2.75, ry(i), 0]} Math(NAMES[i], 0.76, SLATE),
    center{[-1.2, ry(i), 0]} Math("0\,.", 0.85, INK),
    map(range(1, 8), |k| center{[dx(k), ry(i), 0]} Math(to_string(digit(NUMS[i], k)), 0.85, [INK, EMBER][to_int(k == i + 1)])),
    center{[dx(8) + 0.05, ry(i), 0]} Math("\dots", 0.8, SLATE)
]
let NewDigit = |k| center{[dx(k), XR, 0]} Math(to_string(flip(digit(NUMS[k - 1], k))), 0.9, LEAF)
mesh table = []
mesh diag = []
mesh fresh = []
mesh words = []

slide "A list of real numbers between 0 and 1, written as decimals. Suppose someone claims that the list, continued forever, contains every such number."
    table = [
        map(range(0, 7), |i| Row(i)),
        FrameBox(-3.35, 3.35, XR - 0.3, XR + 0.3, MIST, 2),
        map(range(1, 8), |k| FrameBox(dx(k) - 0.2, dx(k) + 0.2, XR - 0.19, XR + 0.19, MIST, 2))
    ]
    play Fade(0.6)

slide "Mark the diagonal: digit 1 of the first number, digit 2 of the second, digit 3 of the third, and so on."
    for (i in range(0, 7)) {
        diag .= FrameBox(dx(i + 1) - 0.2, dx(i + 1) + 0.2, ry(i) - 0.19, ry(i) + 0.19, EMBER, 3)
        play Fade(0.2, [&diag])
    }

slide "Build a new number x one digit at a time: where the diagonal digit is 5 write 6, and where it is anything else write 5."
    fresh = [
        center{[-2.75, XR, 0]} Math("x", 0.9, LEAF),
        center{[-1.2, XR, 0]} Math("0\,.", 0.9, LEAF)
    ]
    play Fade(0.4, [&fresh])
    for (k in range(1, 8)) {
        fresh .= NewDigit(k)
        play Fade(0.35, [&fresh])
    }
    fresh .= center{[dx(8) + 0.05, XR, 0]} Math("\dots", 0.8, LEAF)
    play Fade(0.3, [&fresh])

slide "x differs from the first number in digit 1, from the second in digit 2, and from the nth number in digit n. So x is nowhere on the list."
    words = [center{[0.3, -1.33, 0]} Cap("x differs from row n in digit n", 0.8, ROSE)]
    play Fade(0.5, [&words])

Uses the shared definitions for this lesson's figures.

Steps 1 and 4 are where the $0.4999\ldots = 0.5$ issue is paid for. Without them the argument has a hole: two expansions that differ in a digit can still be the same number, so “differs in the $n$th digit” would not give “is a different number”. Choosing the digits 5 and 6 keeps $x$ away from the only expansions that have this ambiguity.

Cantor first proved this in 1874 by a different method; the diagonal argument comes from a paper of 1891. It follows that $\mathbb{R}$ is uncountable as well: from a list of all real numbers we could strike out those outside $(0, 1)$ and be left with a list of all of $(0,1)$.

Cantor’s theorem: no largest infinity

The diagonal idea does not depend on decimals. For a set $A$, the power set $\mathcal{P}(A)$ is the set of all subsets of $A$. If $A = \{1, 2, 3\}$ then $\mathcal{P}(A)$ has the 8 elements $\varnothing, \{1\}, \{2\}, \{3\}, \{1,2\}, \{1,3\}, \{2,3\}, \{1,2,3\}$. Try to pair the elements of $A$ with subsets of $A$, and describe each subset by a row of yes/no marks.

A function $f$ from $A = \{1, 2, 3, 4\}$ to subsets of $A$, drawn as rows of marks: a filled square in row $a$, column $c$ means $c \in f(a)$. Flipping the diagonal gives a subset $D$ that differs from the row of $f(a)$ in column $a$, so $D$ is not one of the rows.
Monocurl source
let F = [[1, 2], [3], [1, 3, 4], []]
let ELS = [1, 2, 3, 4]
let has = |a, c| to_int(c in F[a - 1])
let setstr = |lst| ["\varnothing", str_join(["\{", str_join(map(lst, |e| to_string(e)), ", "), "\}"])][to_int(len(lst) > 0)]
let D = filter(ELS, |a| has(a, a) == 0)
let cx = |c| 0.2 + (c - 1) * 0.8
let ry = |a| 1.05 - (a - 1) * 0.62
let DY = -1.6
let Mark = |pos, v, col| center{pos} fill{[PAPER, col][v]} stroke{[SLATE, col][v], 2.5} Rect([0.42, 0.42])
mesh table = [
    map(ELS, |c| center{[cx(c), 1.7, 0]} Math(to_string(c), 0.85, SLATE)),
    map(ELS, |a| center{[-2.0, ry(a), 0]} Math(str_join(["f(", to_string(a), ") = ", setstr(F[a - 1])]), 0.82, INK)),
    map(ELS, |a| map(ELS, |c| Mark([cx(c), ry(a), 0], has(a, c), AZURE)))
]
mesh diag = []
mesh flipped = []
mesh words = []

slide "flip"
    play Wait(0.8)
    for (a in ELS) {
        diag .= FrameBox(cx(a) - 0.3, cx(a) + 0.3, ry(a) - 0.3, ry(a) + 0.3, EMBER, 3.5)
        flipped .= Mark([cx(a), DY, 0], 1 - has(a, a), LEAF)
        play Fade(0.6, [&diag, &flipped])
        play Wait(0.3)
    }
    words = [
        center{[-2.0, DY, 0]} Math(str_join(["D = ", setstr(D)]), 0.9, LEAF)
    ]
    play Fade(0.5, [&words])
    play Wait(2.4)

Uses the shared definitions for this lesson's figures.

In the figure $D = \{2, 4\}$: it contains $a$ exactly when $f(a)$ does not. That one sentence is the whole proof, for every set.

For a finite set with $n$ elements the theorem says $n < 2^n$. For infinite sets it gives $|\mathbb{N}| < |\mathcal{P}(\mathbb{N})| < |\mathcal{P}(\mathcal{P}(\mathbb{N}))| < \cdots$, an unending ladder, so there is no largest infinite size. The set $D$ is built the way Russell’s set was in the previous lesson, with $a \notin f(a)$ in place of $x \notin x$.

Worked examples

Common mistakes and edge cases

An edge case in the definitions: “uncountable” does not mean “infinite and hard to list”. The rationals have no listing in order of size, and they are countable all the same, because some other listing works. To prove a set uncountable you must defeat every possible list at once.

The continuum hypothesis

We now have two infinite sizes, $|\mathbb{N}|$ and $|\mathbb{R}|$. A further theorem, which we state without proof, says that $|\mathbb{R}| = |\mathcal{P}(\mathbb{N})|$; its proof describes a real number through its binary expansion, which is a set of positions holding a 1. Cantor asked whether anything lies in between.

Cantor believed it and could not prove it, and Hilbert put it first on his 1900 list of problems for the new century. Kurt Gödel showed in 1940 that the continuum hypothesis cannot be disproved from the standard axioms of set theory (called ZFC), and Paul Cohen showed in 1963 that it cannot be proved from them either, in both cases assuming those axioms are consistent. The hypothesis is independent of the axioms: adding it gives a consistent mathematics, and so does adding its negation.

Stepping back

The hard step was the first one, giving up “a part is smaller than the whole” in favor of pairing. After that, proving two sets the same size is a matter of exhibiting a list, and the craft is in arranging things so that every element is reached after finitely many steps: alternate, or sweep finite diagonals. Proving two sets different in size is harder, because it means defeating all pairings, and the diagonal construction is the tool: let the supposed pairing itself tell you how to build something it missed. The same construction gives Russell’s paradox and Cantor’s theorem, and in computer science it shows that some problems cannot be solved by any program.

Check yourself

Which of these sets is not countable?

Problems

Problems 1 to 3 repeat the moves of the lesson, 4 and 5 combine them, and 6 and 7 go further.

Problem 1

(a) Give a bijection from $\mathbb{N}$ to the set of odd counting numbers and prove that it is one. (b) Give a bijection from $\mathbb{N}$ to $\{10, 11, 12, \dots\}$.

Show solutionHide solution

(a) $f(n) = 2n - 1$. Injective: $2n - 1 = 2n' - 1$ gives $n = n'$. Surjective: an odd counting number is $m = 2k - 1$ for some counting number $k$ (namely $k = \frac{m+1}{2}$, an integer at least 1 because $m$ is odd and at least 1), and $f(k) = m$. (b) $g(n) = n + 9$, with $g(1) = 10$. If $n + 9 = n' + 9$ then $n = n'$, and each $m \geq 10$ is $g(m - 9)$ with $m - 9 \geq 1$.

Problem 2

In the listing $0, 1, -1, 2, -2, \dots$ of the integers, at which positions do $50$ and $-50$ appear? Which integer is at position 99?

Show solutionHide solution

By the formula in the proof, the positive integer $k$ is at position $2k$ and $-k$ is at position $2k + 1$. So 50 is at position 100 and $-50$ at position 101. Position 99 is odd, $99 = 2 \cdot 49 + 1$, so it holds $-49$.

Problem 3

Let $A = \{1, 2, 3\}$ and let $f : A \to \mathcal{P}(A)$ be given by $f(1) = \{2, 3\}$, $f(2) = \{2\}$, $f(3) = \varnothing$. Find the set $D$ from the proof of Cantor’s theorem and check directly that it is not an output of $f$.

Show solutionHide solution

$D = \{a \in A : a \notin f(a)\}$. Since $1 \notin \{2, 3\}$, $1 \in D$. Since $2 \in \{2\}$, $2 \notin D$. Since $3 \notin \varnothing$, $3 \in D$. So $D = \{1, 3\}$. It differs from $f(1) = \{2,3\}$ on the element 1, from $f(2) = \{2\}$ on the element 2 (which is in $f(2)$ and not in $D$), and from $f(3) = \varnothing$ on the element 3.

Problem 4

A list of real numbers begins $r_1 = 0.50000\ldots$, $r_2 = 0.25555\ldots$, $r_3 = 0.33333\ldots$, $r_4 = 0.12345\ldots$, $r_5 = 0.99995\ldots$ Find the first five digits of the diagonal number $x$ from the proof. You know only five digits of $x$ and five digits of $r_2$. Why can you already be sure that $x \neq r_2$?

Show solutionHide solution

The diagonal digits are $a_{11} = 5$, $a_{22} = 5$, $a_{33} = 3$, $a_{44} = 4$, $a_{55} = 5$. The rule gives $d_1 = 6$, $d_2 = 6$, $d_3 = 5$, $d_4 = 5$, $d_5 = 6$, so $x = 0.66556\ldots$ The expansion of $x$ differs from that of $r_2$ in the second digit (6 against 5). All digits of $x$ are 5 or 6, so $x$ has only one decimal expansion, and a number with only one expansion cannot equal a number whose expansion is different. The later digits do not matter.

Problem 5

Let $B$ be the set of all infinite sequences of 0s and 1s, such as $0, 1, 1, 0, 1, \dots$ (a) Prove that $B$ is uncountable. (b) Why is there no need to worry about a “$0.4999\ldots$ problem” here? (c) Show that the set of finite strings of 0s and 1s is countable.

Show solutionHide solution

(a) Let $f : \mathbb{N} \to B$ be any function, and write $f(n) = (b_{n1}, b_{n2}, b_{n3}, \dots)$. Define a sequence $t$ by $t_n = 1 - b_{nn}$. Then $t \in B$, and for each $n$ the sequences $t$ and $f(n)$ differ in the $n$th term, so $t \neq f(n)$. So $f$ is not surjective, and no bijection exists; $B$ is also infinite, so it is uncountable. (b) Two sequences are equal only when all their terms agree, by definition. The elements of $B$ are the sequences themselves, not numbers represented by them, so two different sequences are never the same element. (c) List the strings by length, and within each length in dictionary order: the empty string, then $0, 1$, then $00, 01, 10, 11$, and so on. There are $2^k$ strings of length $k$, a finite number, so every string is reached after finitely many steps and appears once.

Problem 6

A student argues: “The rationals between 0 and 1 are uncountable. Take any list of them, and form the diagonal number $x$. It is not on the list. So no list is complete.” Find the error. Then explain what, if anything, the argument does prove about $x$.

Show solutionHide solution

The diagonal construction produces a real number $x$ that is not on the list. To contradict “the list contains every rational in $(0,1)$” one would need $x$ to be rational, and nothing in the construction provides that. So there is no contradiction. In fact the rationals in $(0, 1)$ are countable, so a complete list exists, and for that list the argument proves that $x$ is irrational: $x$ is a real number in $(0, 1)$ different from every rational in $(0, 1)$.

Problem 7

(a) Let $S$ and $T$ be countably infinite sets with no element in common. Prove that $S \cup T$ is countably infinite. (b) Deduce that the set of irrational numbers is uncountable.

Show solutionHide solution

(a) Let $s_1, s_2, \dots$ and $t_1, t_2, \dots$ be lists of $S$ and $T$ in which each element appears once. Interleave them: $s_1, t_1, s_2, t_2, \dots$, that is, $h(2k - 1) = s_k$ and $h(2k) = t_k$. Every element of $S \cup T$ is some $s_k$ or some $t_k$, so it appears. No element appears twice, because the $s_k$ are distinct, the $t_k$ are distinct, and no $s_k$ equals a $t_j$ since the sets are disjoint. So $h$ is a bijection from $\mathbb{N}$ to $S \cup T$. (b) Suppose, for contradiction, that the set $I$ of irrational numbers is countable. It is not finite: the numbers $\sqrt 2 + n$ for $n = 1, 2, 3, \dots$ are all irrational (if $\sqrt 2 + n$ were a rational $r$, then $\sqrt 2 = r - n$ would be rational) and all different. So $I$ is countably infinite. The set $\mathbb{Q}$ is countably infinite, and $\mathbb{Q}$ and $I$ have no element in common. By part (a), $\mathbb{R} = \mathbb{Q} \cup I$ is countably infinite. But $\mathbb{R}$ is uncountable. This contradiction shows that $I$ is uncountable. In this sense almost all real numbers are irrational.

Shared definitions used by this lesson's figures
# house kit: prepended to every essay figure after the std imports

# palette. AZURE and EMBER are the two actors, LEAF marks an answer, ROSE a problem
let PAPER = [1, 1, 1, 1]
let INK = [0.08, 0.09, 0.11, 1]
let SLATE = [0.40, 0.44, 0.50, 1]
let MIST = [0.85, 0.86, 0.88, 1]
let AZURE = [0.13, 0.42, 0.68, 1]
let EMBER = [0.89, 0.42, 0.12, 1]
let LEAF = [0.13, 0.55, 0.36, 1]
let ROSE = [0.78, 0.22, 0.24, 1]
let PLUM = [0.47, 0.30, 0.66, 1]
let GOLD = [0.85, 0.62, 0.08, 1]

background = PAPER

# an opaque pastel of col; use for fills so overlaps do not darken
let tint = |col, amount = 0.18| [
    1 - (1 - col[0]) * amount,
    1 - (1 - col[1]) * amount,
    1 - (1 - col[2]) * amount,
    1
]

# text: Cap for labels, Note for quiet labels, Math for typeset maths
let Cap = |txt, size = 0.75, col = INK| color{col} Text(txt, size, "Charter")
let Note = |txt, size = 0.65| color{SLATE} Text(txt, size, "Charter")
let Math = |tex, size = 0.9, col = INK| color{col} Tex(tex, size)

# a paper rectangle to sit behind text that crosses lines
let Plate = |pos, size| center{pos} fill{PAPER} stroke{alpha{0} PAPER, 0} Rect(size)

# shapes with fill and stroke both set, so no stray black appears
let Pt = |pos, col = INK, r = 0.075| center{pos} fill{col} stroke{col, 1} Circle(r, 48)
let Ring = |pos, col = INK, r = 0.1, w = 3| center{pos} fill{PAPER} stroke{col, w} Circle(r, 48)
let Seg = |a, b, col = INK, w = 3| stroke{col, w} Line(a, b)
let Path = |pts, col = INK, w = 3| stroke{col, w} Polyline(pts)
let Region = |pts, col| fill{col} stroke{alpha{0} col, 0} Polygon(pts)
let Outline = |pts, col = INK, w = 3| fill{alpha{0} PAPER} stroke{col, w} Polygon(pts)
let Shape = |pts, col, amount = 0.18, w = 3| fill{tint(col, amount)} stroke{col, w} Polygon(pts)
let Disc = |pos, r, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Circle(r, 96)
let Box = |pos, size, col, amount = 0.18, w = 3| center{pos} fill{tint(col, amount)} stroke{col, w} Rect(size)
# a line from a to b ending in a small solid arrowhead
let Tip = |a, b, col = INK, w = 3, head = 0.17| {
    let d = normalize([b[0] - a[0], b[1] - a[1], 0])
    let n = [-d[1], d[0], 0]
    let base = [b[0] - d[0] * head, b[1] - d[1] * head, 0]
    return [
        stroke{col, w} Line(a, base),
        fill{col} stroke{col, 1} Polygon([
            b,
            [base[0] + n[0] * head * 0.42, base[1] + n[1] * head * 0.42, 0],
            [base[0] - n[0] * head * 0.42, base[1] - n[1] * head * 0.42, 0]
        ])
    ]
}

# plots. a frame is [x0, x1, y0, y1, centre, width, height]: a data window and the scene box it fills
let Frame = |x0, x1, y0, y1, c = [0, 0, 0], w = 6.4, h = 3.6| [x0, x1, y0, y1, c, w, h]
let fx = |fr, x| fr[4][0] + (x - (fr[0] + fr[1]) / 2) * fr[5] / (fr[1] - fr[0])
let fy = |fr, y| fr[4][1] + (y - (fr[2] + fr[3]) / 2) * fr[6] / (fr[3] - fr[2])
let at = |fr, x, y| [fx(fr, x), fy(fr, y), 0]

# axes through the data origin (or the nearest edge of the window), with optional names
let Axes = |fr, x_name = "", y_name = "", col = SLATE| {
    let ox = clamp(fr[0], 0, fr[1])
    let oy = clamp(fr[2], 0, fr[3])
    var parts = [
        Tip(at(fr, fr[0], oy), [fx(fr, fr[1]) + 0.25, fy(fr, oy), 0], col, 2.5, 0.15),
        Tip(at(fr, ox, fr[2]), [fx(fr, ox), fy(fr, fr[3]) + 0.25, 0], col, 2.5, 0.15)
    ]
    if (x_name != "") {
        parts .= center{[fx(fr, fr[1]) + 0.5, fy(fr, oy), 0]} Math(x_name, 0.8, col)
    }
    if (y_name != "") {
        parts .= center{[fx(fr, ox), fy(fr, fr[3]) + 0.5, 0]} Math(y_name, 0.8, col)
    }
    return parts
}

# tick marks with numbers at the listed data values
let XTicks = |fr, xs, col = SLATE, places = 0| block {
    let oy = fy(fr, clamp(fr[2], 0, fr[3]))
    for (x in xs) {
        . Seg([fx(fr, x), oy - 0.07, 0], [fx(fr, x), oy + 0.07, 0], col, 2)
        . center{[fx(fr, x), oy - 0.33, 0]} Math(to_string(x, places), 0.72, col)
    }
}
let YTicks = |fr, ys, col = SLATE, places = 0| block {
    let ox = fx(fr, clamp(fr[0], 0, fr[1]))
    for (y in ys) {
        . Seg([ox - 0.07, fy(fr, y), 0], [ox + 0.07, fy(fr, y), 0], col, 2)
        . center{[ox - 0.36, fy(fr, y), 0]} Math(to_string(y, places), 0.72, col)
    }
}

# faint grid lines at the listed data values
let GridLines = |fr, xs, ys, col = MIST| block {
    for (x in xs) {
        . Seg(at(fr, x, fr[2]), at(fr, x, fr[3]), col, 1.5)
    }
    for (y in ys) {
        . Seg(at(fr, fr[0], y), at(fr, fr[1], y), col, 1.5)
    }
}

# the graph of f over [a, b], drawn in the frame. values are clamped to the window
let Graph = |fr, f, a, b, col = AZURE, w = 4, n = 160|
    stroke{col, w} Polyline(map(sample(a, b, n), |x| at(fr, x, clamp(fr[2], f(x), fr[3]))))

# the region between the graph of f and the x axis over [a, b]
let AreaUnder = |fr, f, a, b, col = AZURE, amount = 0.2, n = 80| {
    var pts = [at(fr, a, 0)]
    for (x in sample(a, b, n)) {
        pts .= at(fr, x, clamp(fr[2], f(x), fr[3]))
    }
    pts .= at(fr, b, 0)
    return fill{tint(col, amount)} stroke{alpha{0} col, 0} Polygon(pts)
}

let FrameBox = |x0, x1, y0, y1, col, w = 4.5| Outline([[x0, y0, 0], [x1, y0, 0], [x1, y1, 0], [x0, y1, 0]], col, w)
let NumTile = |pos, txt, col, w = 0.56, h = 0.5, size = 0.76, amount = 0.15| [
    Box(pos, [w, h], col, amount, 2.5),
    center{pos} Math(txt, size, col)
]