Monocurl Essays
Series Download

The law of large numbers, and the gambler's fallacy

A fair coin has no memory, yet its share of heads settles at one half. The weak law of large numbers says exactly how, and Chebyshev's inequality proves it.

22 min·High school and early college·

AssumesExpected value and the surprising power of adding averagesBinomial distribution: Pascal's triangle and a Galton board

A simulation of 30 separate runs of 1000 flips of a fair coin. Each curve is one run’s share of heads so far. The runs disagree wildly at first and are all squeezed toward one half as the flips accumulate.
Monocurl source
let RUNS = 30
let NF = 1000
var idx = []
for (k in range(1, 21)) {
    idx .= k
}
for (k in range(25, 101, 5)) {
    idx .= k
}
for (k in range(110, NF + 1, 10)) {
    idx .= k
}
let IDX = idx
var paths = []
for (r in range(0, RUNS)) {
    var h = 0
    var q = 0
    var pts = []
    for (i in range(1, NF + 1)) {
        h = h + flip(i, 20 + r)
        if (i == IDX[q]) {
            pts .= h / i
            q = min(q + 1, len(IDX) - 1)
        }
    }
    paths .= pts
}
let PATHS = paths
let fs = Frame(0, NF, 0, 1, [-0.1, 0.12, 0], 6.3, 3.0)
let COLS = [AZURE, PLUM, SLATE]
let Funnel = |j| {
    let k = to_int(floor(j))
    var parts = []
    for (r in range(0, RUNS)) {
        parts .= stroke{alpha{0.55} COLS[to_int(mod(r, 3))], 2} Polyline(map(range(0, k + 1), |m| at(fs, IDX[m], PATHS[r][m])))
    }
    parts .= stroke{EMBER, 3.5} Polyline(map(range(0, k + 1), |m| at(fs, IDX[m], PATHS[0][m])))
    parts .= center{[2.6, 0.88, 0]} scale{1.25} color{INK} Number(IDX[k], 0)
    return parts
}
mesh frame = [
    GridLines(fs, [250, 500, 750, 1000], [0.25, 0.5, 0.75, 1]),
    Axes(fs),
    XTicks(fs, [250, 500, 750, 1000]),
    YTicks(fs, [0.25, 0.5, 0.75, 1], SLATE, 2),
    center{[fx(fs, 500), fy(fs, 0) - 0.66, 0]} Note("flips", 0.74),
    center{[fx(fs, 0) + 1.1, fy(fs, 1) + 0.36, 0]} Note("share of heads", 0.74),
    center{[1.6, 1.3, 0]} Cap("simulation: 30 runs", 0.76, SLATE),
    center{[1.6, 0.88, 0]} Cap("flips so far:", 0.76, INK)
]
mesh half = stroke{LEAF, 2.5} dashed{[0.14, 0.09]} Line(at(fs, 0, 0.5), at(fs, NF, 0.5))
mesh funnel = Funnel(j: 1)

slide "run"
    play Wait(0.4)
    funnel.j = len(IDX) - 1
    play Lerp(8, [&funnel], linear)
    play Wait(1.8)

Uses the shared definitions for this lesson's figures.

At a roulette table, red has just come up eight times in a row. A crowd gathers, and most of it bets on black. The reasoning sounds solid: in the long run red and black come up equally often, the wheel is now eight reds ahead, so black is due.

On the other side stands a fact nobody at the table would deny if asked directly. The wheel is a lump of wood and metal. It has no record of its last eight spins and no means of consulting one.

Both beliefs are held by sensible people, often by the same person, and they pull in opposite directions. The second says the next spin is like any other. The first says long-run proportions even out, and seems to need the wheel to compensate. The crowd’s conclusion has a name, the gambler’s fallacy, and a famous casualty list: at Monte Carlo in 1913, the story goes, black came up 26 times in a row while players lost fortunes betting that red was due. This lesson is about how both beliefs can be true at once. Proportions do even out, and they do it without any compensation.

To keep the arithmetic clean, I will replace the wheel by a fair coin, with heads for red and tails for black. (A real wheel also has one or two green pockets, which changes the numbers slightly and the argument not at all.)

The coin has no memory

Pause and try

A fair coin is flipped nine times. Given that the first eight flips were all heads, what is the probability that the ninth is heads? Compute it from the sample space of all sequences of nine flips.

Show answerHide answer

There are $2^9 = 512$ equally likely sequences. Exactly two of them begin with eight heads: HHHHHHHHH and HHHHHHHHT. One of those two ends in heads, so the conditional probability is $\frac12$. In symbols, with the definition $P(A \mid B) = P(A \cap B)/P(B)$, it is $\frac{1/512}{2/512} = \frac12$.

The run of nine heads and the run of eight heads followed by a tail are single sequences, and every single sequence of nine flips has the same probability, $\frac{1}{512}$. A streak feels as if it should be harder to extend than to break, but the two continuations are one sequence each.

This is a prediction about frequencies, so it can be tested. First, streaks themselves are ordinary. Here are 200 simulated flips.

A simulation of 200 flips of a fair coin, read left to right and top to bottom. Heads are blue and tails are orange, and the longest streak of equal results is boxed. A streak of eight or more somewhere in 200 flips happens more often than not.
A simulation of 200 flips of a fair coin, read left to right and top to bottom. Heads are blue and tails are orange, and the longest streak of equal results is boxed. A streak of eight or more somewhere in 200 flips happens more often than not.
Monocurl source
let NS = 200
let COLS = 20
let GAP = 0.33
let F = map(range(0, NS), |i| flip(i + 1, 8))
var best = 1
var best_end = 0
var run = 1
for (i in range(1, NS)) {
    if (F[i] == F[i - 1]) {
        run = run + 1
    } else {
        run = 1
    }
    if (run > best) {
        best = run
        best_end = i
    }
}
let BEST = best
let BEST_END = best_end
let pos = |i| [-3.13 + mod(i, COLS) * GAP, 1.9 - (i // COLS) * GAP, 0]
mesh hi = map(range(BEST_END - BEST + 1, BEST_END + 1), |i| center{pos(i)} fill{tint(PLUM, 0.3)} stroke{PLUM, 2.5} Rect([GAP, GAP]))
mesh dots = map(range(0, NS), |i| Pt(pos(i), [EMBER, AZURE][F[i]], 0.105))
mesh legend = [
    Pt([-3.1, -1.68, 0], AZURE, 0.105),
    center{[-2.55, -1.68, 0]} Cap("heads", 0.78, AZURE),
    Pt([-1.7, -1.68, 0], EMBER, 0.105),
    center{[-1.22, -1.68, 0]} Cap("tails", 0.78, EMBER),
    center{[1.75, -1.68, 0]} Cap(str_join(["longest streak: ", to_string(BEST), " in a row"]), 0.78, PLUM)
]

Uses the shared definitions for this lesson's figures.

An exact calculation, which I will not reproduce, shows that 200 fair flips contain a streak of at least eight equal results with probability about 0.54. Eight reds in a row is what a fair wheel looks like on a typical evening.

Second, and more to the point, we can ask the simulation what happens after such a streak.

A simulation of 100,000 flips of a fair coin. Every time eight heads in a row occurred, the next flip was recorded. The next flip was heads about as often as tails: the streak told us nothing.
A simulation of 100,000 flips of a fair coin. Every time eight heads in a row occurred, the next flip was recorded. The next flip was heads about as often as tails: the streak told us nothing.
Monocurl source
let NS = 100000
var streak = 0
var next_h = 0
var next_t = 0
for (i in range(1, NS + 1)) {
    let f = flip(i, 4)
    if (streak >= 8) {
        if (f) {
            next_h = next_h + 1
        } else {
            next_t = next_t + 1
        }
    }
    if (f) {
        streak = streak + 1
    } else {
        streak = 0
    }
}
let NH = next_h
let NT = next_t
let W = 5.2
let Bar = |y, n, col, name| [
    Box([-3.0 + W * n / (NH + NT) / 2 + 0.6, y, 0], [W * n / (NH + NT), 0.62], col, 0.3, 3),
    center{[-3.0, y, 0]} Cap(name, 0.8, col),
    center{[-2.4 + W * n / (NH + NT) + 0.95, y, 0]} Cap(str_join([to_string(n), " times"]), 0.8, col)
]
mesh top = [
    map(range(0, 8), |k| Pt([-2.3 + k * 0.42, 1.35, 0], AZURE, 0.14)),
    Ring([-2.3 + 8 * 0.42 + 0.1, 1.35, 0], PLUM, 0.17, 3.5),
    center{[-2.3 + 8 * 0.42 + 0.1, 1.35, 0]} Cap("?", 0.8, PLUM),
    center{[2.75, 1.35, 0]} Cap("then what?", 0.8, PLUM)
]
mesh bars = [
    Bar(0.1, NH, AZURE, "heads"),
    Bar(-0.8, NT, EMBER, "tails"),
    center{[0, -1.75, 0]} Note(str_join(["simulation: 100,000 flips, ", to_string(NH + NT), " streaks of eight heads"]), 0.74)
]

Uses the shared definitions for this lesson's figures.

In this run eight heads in a row occurred 399 times, and the next flip was heads 198 times and tails 201 times. A gap of three is far inside what chance allows: in 399 fair flips the number of heads has standard deviation $\sqrt{399}/2 \approx 10$. So the second belief survives the test: the next flip is 50-50 whatever came before. The work is in explaining the first belief without contradicting it.

How a share converges without compensation

The crowd’s picture is that an excess of heads has to be paid back by a later excess of tails. Let us see what happens to the share of heads if nothing is paid back at all.

Suppose the first 8 flips are heads, and that from then on the coin does the most ordinary thing possible, producing heads and tails in exactly equal numbers. After 92 more flips there are $8 + 46 = 54$ heads in 100 flips, a share of 0.54. After 992 more there are $8 + 496 = 504$ heads in 1000, a share of 0.504. The lead of heads over tails is 8 the whole time. It is never repaid, and the share of heads approaches $\frac12$ anyway.

Eight heads to start, followed by flips that split exactly evenly. The bar shows the makeup of all flips so far. The lead of heads over tails stays at 8, but as a share of a growing total the eight early heads shrink toward nothing and the share of heads approaches one half.
Monocurl source
let L = -3.2
let W = 6.4
let Y = 0.75
let HT = 1.15
let Mix = |m| {
    let n = 8 + m
    let a = L + W * 8 / n
    let b = L + W * (8 + m / 2) / n
    return [
        Region([[L, Y - HT / 2, 0], [a, Y - HT / 2, 0], [a, Y + HT / 2, 0], [L, Y + HT / 2, 0]], EMBER),
        Region([[a, Y - HT / 2, 0], [b + 0.001, Y - HT / 2, 0], [b + 0.001, Y + HT / 2, 0], [a, Y + HT / 2, 0]], tint(AZURE, 0.55)),
        Region([[b, Y - HT / 2, 0], [L + W, Y - HT / 2, 0], [L + W, Y + HT / 2, 0], [b, Y + HT / 2, 0]], tint(SLATE, 0.22)),
        Outline([[L, Y - HT / 2, 0], [L + W, Y - HT / 2, 0], [L + W, Y + HT / 2, 0], [L, Y + HT / 2, 0]], SLATE, 2.5),
        Seg([b, Y - HT / 2 - 0.12, 0], [b, Y + HT / 2 + 0.12, 0], INK, 3.5),
        center{[-2.4, -1.45, 0]} scale{1.3} color{INK} Number(round(n), 0),
        center{[0, -1.45, 0]} scale{1.3} color{EMBER} Number(8, 0),
        center{[2.4, -1.45, 0]} scale{1.3} color{AZURE} Number((8 + m / 2) / n, 3)
    ]
}
mesh labels = [
    Seg([0, Y + HT / 2 + 0.32, 0], [0, Y - HT / 2 - 0.32, 0], LEAF, 3),
    center{[0, Y + HT / 2 + 0.55, 0]} Cap("one half", 0.76, LEAF),
    center{[-2.3, Y + HT / 2 + 0.55, 0]} Cap("8 early heads", 0.76, EMBER),
    center{[2.2, Y + HT / 2 + 0.55, 0]} Cap("later heads | later tails", 0.76, SLATE),
    center{[-2.4, -0.85, 0]} Cap("flips", 0.78, INK),
    center{[0, -0.85, 0]} Cap("heads minus tails", 0.78, EMBER),
    center{[2.4, -0.85, 0]} Cap("share of heads", 0.78, AZURE)
]
mesh mix = Mix(m: 0)

slide "dilute"
    play Wait(1)
    mix.m = 992
    play Lerp(7, [&mix], |u| u * u * u)
    play Wait(1.6)

Uses the shared definitions for this lesson's figures.

Pause and try

In this scenario, with a permanent lead of 8, how many flips does it take before the share of heads is within 0.001 of one half?

Show answerHide answer

After $n$ flips there are $\frac{n + 8}{2}$ heads, so the share of heads is $\frac12 + \frac{4}{n}$. We need $\frac4n < 0.001$, that is, $n > 4000$. The early streak is still there, outvoted.

So a share can converge while the lead does not shrink. Real flips do something more extreme. The lead does not even stay put: it wanders, and its typical size grows.

A simulation of five runs of 10,000 flips of a fair coin, shown two ways. Top: the share of heads, which closes in on one half. Bottom: heads minus tails for the same five runs, which wanders farther from zero as the flips go on. The dashed curves mark one standard deviation either side of the expected value, computed exactly.
Monocurl source
let NR = 5
let NF = 10000
let STEP = 100
var runs = []
for (r in range(0, NR)) {
    var h = 0
    var pts = [0]
    for (i in range(1, NF + 1)) {
        h = h + flip(i, 60 + r)
        if (mod(i, STEP) == 0) {
            pts .= h
        }
    }
    runs .= pts
}
let HEADS = runs
let fa = Frame(0, NF, 0.44, 0.56, [0.2, 1.25, 0], 6.0, 1.4)
let fd = Frame(0, NF, -160, 160, [0.2, -0.52, 0], 6.0, 1.6)
let COLS = [AZURE, EMBER, PLUM, GOLD, SLATE]
let Both = |j| {
    let k = to_int(floor(j))
    var parts = []
    for (r in range(0, NR)) {
        parts .= stroke{COLS[r], 3.5} Polyline(map(range(1, k + 1), |m| at(fa, m * STEP, clamp(0.44, HEADS[r][m] / (m * STEP), 0.56))))
        parts .= stroke{COLS[r], 3.5} Polyline(map(range(0, k + 1), |m| at(fd, m * STEP, clamp(-160, 2 * HEADS[r][m] - m * STEP, 160))))
    }
    return parts
}
mesh frame = [
    GridLines(fa, [2500, 5000, 7500, 10000], [0.45, 0.5, 0.55]),
    GridLines(fd, [2500, 5000, 7500, 10000], [-100, 0, 100]),
    Seg(at(fa, 0, 0.44), at(fa, 0, 0.56), SLATE, 2.5),
    Seg(at(fd, 0, -160), at(fd, 0, 160), SLATE, 2.5),
    map([0.45, 0.5, 0.55], |v| center{[fx(fa, 0) - 0.42, fy(fa, v), 0]} Math(to_string(v, 2), 0.72, SLATE)),
    map([-100, 0, 100], |v| center{[fx(fd, 0) - 0.45, fy(fd, v), 0]} Math(to_string(v), 0.72, SLATE)),
    map([2500, 5000, 7500, 10000], |v| center{[fx(fd, v), fy(fd, -160) - 0.28, 0]} Math(to_string(v), 0.72, SLATE)),
    center{[fx(fd, 5000), fy(fd, -160) - 0.62, 0]} Note("flips", 0.78),
    center{[fx(fa, 8750), fy(fa, 0.542), 0]} Cap("share of heads", 0.78, INK),
    center{[fx(fd, 1250), fy(fd, 132), 0]} Cap("heads − tails", 0.78, INK),
    center{[fx(fa, 8750), fy(fa, 0.466), 0]} Note("simulation", 0.76)
]
mesh envelope = [
    stroke{SLATE, 3} dashed{[0.1, 0.07]} Polyline(map(sample(100, NF, 100), |n| at(fa, n, 0.5 + 0.5 / sqrt(n)))),
    stroke{SLATE, 3} dashed{[0.1, 0.07]} Polyline(map(sample(100, NF, 100), |n| at(fa, n, 0.5 - 0.5 / sqrt(n)))),
    stroke{SLATE, 3} dashed{[0.1, 0.07]} Polyline(map(sample(1, NF, 80), |n| at(fd, n, sqrt(n)))),
    stroke{SLATE, 3} dashed{[0.1, 0.07]} Polyline(map(sample(1, NF, 80), |n| at(fd, n, -sqrt(n))))
]
mesh both = Both(j: 2)

slide "run"
    play Wait(0.5)
    both.j = NF / STEP
    play Lerp(8, [&both], linear)
    play Wait(1.8)

Uses the shared definitions for this lesson's figures.

The two panels show the same five runs, and they look like opposites: a funnel above, a widening trumpet below. Five runs are too few to establish a trend by themselves, which is why the dashed curves are there: they are computed, and it is they that widen below and narrow above. They are consistent because the top panel divides by the number of flips. If $H$ is the number of heads in $n$ flips, the lead is $H - (n - H) = 2H - n$, and the share is

$$ \frac{H}{n} = \frac12 + \frac{2H - n}{2n}. $$

The lead $2H - n$ typically has size around $\sqrt n$, as we will compute in a moment: about 100 after 10,000 flips. Divided by $2n$ that is 0.005. The lead grows, the number of flips grows faster, and the quotient shrinks. Nothing in this mechanism looks backward at earlier flips.

What “settles near one half” should mean

We now want a theorem. The first task is to decide what it should say, because the obvious candidates are false.

It cannot say that the share of heads is eventually exactly $\frac12$; with an odd number of flips that is impossible. It cannot say that the share is certain to be within, say, 0.1 of $\frac12$ after 100 flips, because 100 heads in a row has probability $2^{-100}$, which is small and not zero. Any honest statement has to be about probability: a large deviation is possible but unlikely, and becomes as unlikely as we please if we flip long enough.

Here is that claim on a real instance. For 100 flips, the binomial formula from the last lesson gives the chance that the share of heads misses $\frac12$ by 0.1 or more, which means 40 or fewer heads or 60 or more, as about 0.057. For 1000 flips, the chance of missing by 0.1 or more is about $3 \times 10^{-10}$.

The exact distribution of the share of heads in 25, 50, 100, 200 and 400 flips of a fair coin, with bar heights scaled to the tallest bar. Outcomes that miss one half by 0.1 or more are red. The chance of landing in the red region falls from 0.42 toward zero, always below the bound that Chebyshev’s inequality provides.
Monocurl source
let NS = [25, 50, 100, 200, 400]
let TABLES = map(NS, |n| fair_table(n))
let OUT = map(NS, |n| outside(n, 10))
let fw = Frame(0.2, 0.8, 0, 1.1, [-0.9, 0.12, 0], 4.8, 2.6)
let Pile = |m| {
    let s = to_int(floor(m + 0.0001))
    let n = NS[s]
    let top = TABLES[s][n // 2]
    var parts = []
    for (k in range(0, n + 1)) {
        let h = TABLES[s][k] / top
        let x = k / n
        if (h > 0.004 and x > 0.2 and x < 0.8) {
            var col = AZURE
            if (abs(2 * k - n) * 10 >= 2 * n - 0.000001) {
                col = ROSE
            }
            parts .= Box(at(fw, x, h / 2), [4.8 / (0.6 * n) * 0.8, h * 2.6 / 1.1], col, 0.35, 1.5)
        }
    }
    parts .= center{[3.0, 1.25, 0]} scale{1.25} color{INK} Number(n, 0)
    parts .= center{[3.0, 0.05, 0]} scale{1.25} color{ROSE} Number(OUT[s], 4)
    parts .= center{[3.0, -1.2, 0]} scale{1.25} color{SLATE} Number(min(25 / n, 1), 4)
    return parts
}
mesh frame = [
    Seg(at(fw, 0.2, 0), at(fw, 0.8, 0), SLATE, 2.5),
    map([0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], |v| [
        Seg([fx(fw, v), fy(fw, 0) - 0.08, 0], [fx(fw, v), fy(fw, 0), 0], SLATE, 2),
        center{[fx(fw, v), fy(fw, 0) - 0.32, 0]} Math(to_string(v, 1), 0.74, SLATE)
    ]),
    stroke{PLUM, 2.5} dashed{[0.12, 0.08]} Line(at(fw, 0.4, 0), at(fw, 0.4, 1.1)),
    stroke{PLUM, 2.5} dashed{[0.12, 0.08]} Line(at(fw, 0.6, 0), at(fw, 0.6, 1.1)),
    center{[fx(fw, 0.5), fy(fw, 0) - 0.66, 0]} Note("share of heads", 0.74),
    center{[fx(fw, 0.5), fy(fw, 1.1) + 0.28, 0]} Cap("within 0.1 of one half", 0.74, PLUM),
    center{[3.0, 1.75, 0]} Cap("flips", 0.78, INK),
    center{[3.0, 0.55, 0]} Cap("chance of red", 0.78, ROSE),
    center{[3.0, -0.7, 0]} Cap("Chebyshev bound", 0.76, SLATE)
]
mesh pile = Pile(m: 0)

slide "grow"
    play Wait(1.2)
    pile.m = 4.5
    play Lerp(7.5, [&pile], linear)
    play Wait(1.5)

Uses the shared definitions for this lesson's figures.

The statement we are after is that the red probability tends to zero, for every choice of tolerance and for any success probability, and we would like a proof that does not depend on evaluating binomial sums. For that we need a way to bound the chance of a large deviation using only the mean and the variance. It is built in two steps.

Markov’s and Chebyshev’s inequalities

Recall from the lesson on expected value that a random variable $X$ on a finite sample space $\Omega$ is a function $X : \Omega \to \mathbb{R}$, and its expected value is $E[X] = \sum_\omega X(\omega)P(\{\omega\})$. From the last lesson, its variance is $\operatorname{Var}(X) = E[(X - \mu)^2]$ where $\mu = E[X]$, and its standard deviation is $\sigma = \sqrt{\operatorname{Var}(X)}$.

The first step is a statement about averages that you already believe. If the average score on a test is 20 and no score is negative, then at most a quarter of the class scored 80 or more: a larger group of 80s would by themselves push the average above 20. The figure shows the same reasoning on a random variable from the last lesson, the squared distance from the mean on an eight-row Galton board.

  1. Each route has a height: its squared distance from the mean. The heights total 512 over 256 routes, an average of 2.
  2. Routes with height at least 4 number 74. A rectangle 74 wide and 4 tall fits inside the area.
  3. So 74 times 4 is at most 512. Dividing by 256 and by 4: the fraction of such routes is at most the mean over 4.
Markov’s inequality as areas. The 256 equally likely routes through an eight-row Galton board are sorted by the squared distance of their bin from the mean. The total area of the bars is 256 times the mean. The routes with squared distance at least 4 contribute a rectangle of height 4 that must fit inside that area.
Monocurl source
let N = 8
let VALS = sort(flatten(map(range(0, N + 1), |k| map(range(0, choose(N, k)), |i| (k - N / 2) ^ 2))))
let TOTAL = sum(VALS)
let A = 4
let BIG = count(VALS, |v| v >= A)
let fm = Frame(0, 256, 0, 17, [-0.1, -0.05, 0], 6.2, 3.1)
let stairs = block {
    . at(fm, 0, 0)
    for (i in range(0, 256)) {
        . at(fm, i, VALS[i])
        . at(fm, i + 1, VALS[i])
    }
    . at(fm, 256, 0)
}
mesh frame = [
    GridLines(fm, [], [4, 9, 16]),
    Seg(at(fm, 0, 0), at(fm, 256, 0), SLATE, 2.5),
    Seg(at(fm, 0, 0), at(fm, 0, 17), SLATE, 2.5),
    map([1, 4, 9, 16], |v| center{[fx(fm, 0) - 0.3, fy(fm, v), 0]} Math(to_string(v), 0.74, SLATE)),
    center{[fx(fm, 128), fy(fm, 0) - 0.35, 0]} Note("the 256 routes, sorted", 0.74),
    center{[fx(fm, 0) + 1.55, fy(fm, 17) + 0.32, 0]} Note("squared distance from the mean", 0.74)
]
mesh area = Region(filter(stairs, |q| 1), tint(AZURE, 0.35))
mesh edge = Path(stairs, AZURE, 2.5)
mesh rect = []
mesh note = []

slide "Each route has a height: its squared distance from the mean. The heights total 512 over 256 routes, an average of 2."
    note = [
        center{[-1.2, 1.2, 0]} Cap(str_join(["total area ", to_string(TOTAL, 0)]), 0.8, AZURE),
        center{[-1.2, 0.7, 0]} Math(str_join(["\text{mean} = \frac{", to_string(TOTAL, 0), "}{256} = ", to_string(TOTAL / 256, 0)]), 0.85, AZURE)
    ]
    play Fade(0.7)

slide "Routes with height at least 4 number 74. A rectangle 74 wide and 4 tall fits inside the area."
    note = []
    play Fade(0.3, [&note])
    rect = [
        Shape([at(fm, 256 - BIG, 0), at(fm, 256, 0), at(fm, 256, A), at(fm, 256 - BIG, A)], PLUM, 0.45, 3.5)
    ]
    note = [
        center{[-1.2, 1.2, 0]} Cap(str_join([to_string(BIG), " routes at height 4 or more"]), 0.78, PLUM)
    ]
    play Fade(0.7)

slide "So 74 times 4 is at most 512. Dividing by 256 and by 4: the fraction of such routes is at most the mean over 4."
    note .= center{[-1.2, 0.45, 0]} Math(str_join([to_string(BIG), " \cdot ", to_string(A), " \le ", to_string(TOTAL, 0)]), 0.9, INK)
    note .= center{[-1.2, -0.3, 0]} Math(str_join(["\frac{", to_string(BIG), "}{256} \le \frac{", to_string(TOTAL / 256, 0), "}{", to_string(A), "}"]), 0.95, INK)
    play Fade(0.6, [&note])

Uses the shared definitions for this lesson's figures.

The hypothesis $Y \ge 0$ is the dropped second sum in the proof and the bars standing on the axis in the figure. Without it the inequality fails: if $Y$ is $10$ or $-10$ with probability $\frac12$ each, then $E[Y] = 0$ while $P(Y \ge 10) = \frac12$.

Markov’s inequality bounds how often a nonnegative quantity is large. We want to bound how often $X$ is far from its mean, in either direction, and $X - \mu$ takes both signs. The repair is the one the figure already used: square the deviation. The variable $(X - \mu)^2$ is never negative, its mean is the variance, and “far from the mean” is the same as “squared distance large”.

In the figure, $X$ is the bin, $\mu = 4$, the variance is 2 and $t = 2$: the chance of landing 2 or more bins from the middle is at most $\frac24$. The true value is $\frac{74}{256} \approx 0.29$. Chebyshev’s inequality is seldom close to the truth. Its strength is that it asks for nothing except a mean and a variance.

The weak law of large numbers

We need one small fact about variance before the main theorem. For constants $a$ and $b$,

$$ \operatorname{Var}(aX + b) = a^2 \operatorname{Var}(X). $$

This holds because $aX + b$ has mean $a\mu + b$ by linearity, so its deviation from its mean is $a(X - \mu)$, whose square is $a^2 (X - \mu)^2$. Shifting a variable does not change its spread, and scaling it by $a$ scales the squared spread by $a^2$.

From the last lesson: in $n$ independent trials, each succeeding with probability $p$, the number of successes $S_n$ has $E[S_n] = np$ and $\operatorname{Var}(S_n) = np(1-p)$. For the fair coin that is variance $\frac n4$, so the lead $2S_n - n$ has variance $4 \cdot \frac n4 = n$ and standard deviation $\sqrt n$, as promised above. The share of successes $S_n / n$ has mean $p$ and variance

$$ \operatorname{Var}\!\left(\frac{S_n}{n}\right) = \frac{1}{n^2} \cdot np(1-p) = \frac{p(1-p)}{n}. $$

The variance of the share shrinks like $\frac1n$. Chebyshev’s inequality converts that into a statement about probability.

Read the statement as a challenge and a reply. You choose a tolerance $\varepsilon$, as small as you like. The theorem replies that the chance of the observed share missing $p$ by $\varepsilon$ or more is at most $\frac{1}{4n\varepsilon^2}$, which can be made as small as you like by taking $n$ large. Jacob Bernoulli proved a version of this in a book published in 1713, by a much longer route; the short proof came with Chebyshev’s inequality, which Bienaymé had stated before Chebyshev used it in 1867.

For the fair coin with $\varepsilon = 0.1$ the bound is $\frac{25}{n}$: 0.25 at $n = 100$, where the true value is 0.057, and 0.025 at $n = 1000$, where the true value is below a billionth. The bound is crude, and it still does the job of going to zero.

The chance that the share of heads in n fair flips misses one half by 0.1 or more: the exact value (blue) and the Chebyshev bound 25/n (orange). The bound is far above the truth, and both go to zero.
The chance that the share of heads in $n$ fair flips misses one half by 0.1 or more: the exact value (blue) and the Chebyshev bound $25/n$ (orange). The bound is far above the truth, and both go to zero.
Monocurl source
let fe = Frame(0, 400, 0, 1, [0.1, 0.15, 0], 6.0, 2.9)
let NSV = range(10, 401, 10)
mesh frame = [
    GridLines(fe, [100, 200, 300, 400], [0.25, 0.5, 0.75, 1]),
    Axes(fe),
    XTicks(fe, [100, 200, 300, 400]),
    YTicks(fe, [0.25, 0.5, 0.75, 1], SLATE, 2),
    center{[fx(fe, 200), fy(fe, 0) - 0.68, 0]} Note("number of flips", 0.74),
    center{[fx(fe, 0) + 2.0, fy(fe, 1) + 0.36, 0]} Note("chance of missing by 0.1 or more", 0.74)
]
mesh bound = Path(map(sample(25, 400, 120), |n| at(fe, n, 25 / n)), EMBER, 4)
mesh exact = [
    Path(map(NSV, |n| at(fe, n, outside(n, 10))), AZURE, 3),
    map(NSV, |n| Pt(at(fe, n, outside(n, 10)), AZURE, 0.05))
]
mesh labels = [
    center{at(fe, 150, 25 / 100) + [0.2, 0.42, 0]} Cap("Chebyshev bound", 0.78, EMBER),
    center{at(fe, 34, 0.1)} Cap("exact", 0.78, AZURE)
]

Uses the shared definitions for this lesson's figures.

The law and the fallacy, side by side

Now return to the table, eight reds down. The law of large numbers is a statement about a share over many trials. Applied to the next 1000 spins, which are independent of the past, it says their share of red will probably be close to one half. It does not say close to a little less than one half, to make up for the eight.

Pause and try

After 8 heads in a row, a fair coin is flipped 1000 more times. What is the expected number of heads in all 1008 flips, and the expected lead of heads over tails at the end?

Show answerHide answer

The 1000 later flips have expected value 500 heads and 500 tails, whatever came first. So the expected totals are 508 heads and 500 tails, and the expected lead is still 8. The expected share of heads is $\frac{508}{1008} \approx 0.504$: closer to one half than $\frac88$, with nothing repaid.

It is also worth being exact about what the weak law does not promise.

It does not say the counts of heads and tails become close. The lead has standard deviation $\sqrt n$, which grows without bound.

It does not say anything about short runs. With $\varepsilon = 0.1$ and $n = 10$ the bound $\frac{1}{4n\varepsilon^2}$ is 2.5, which is no information at all.

It needs its hypotheses. Suppose a coin is flipped once and the result is copied down $n$ times. Each entry is heads with probability $\frac12$, but the entries are as dependent as they could be, and the share of heads is 0 or 1 for every $n$. The proof breaks at the variance: for this $S_n$ the variance is $\frac{n^2}{4}$, so the variance of the share is $\frac14$ and does not shrink.

Finally, the weak law concerns one large $n$ at a time. A stronger theorem, the strong law of large numbers, says that with probability 1 the whole infinite sequence of shares converges to $p$. Its proof needs tools beyond this lesson and we do not use it.

Worked examples

Common mistakes

Stepping back

The difficulty here was a phrase: “evens out”. Read as a statement about counts, it is false, since the gap between heads and tails typically widens. Read as a statement about shares, it is true, and the reason is division by a growing $n$. Once the two readings are separated, the wheel’s lack of memory and the long-run frequency stop competing.

The proof is worth remembering as a pattern. Markov’s inequality turns a mean into a bound on a probability. Squaring the deviation turns that into Chebyshev’s inequality, which needs only a variance. And the variance of an average of independent trials shrinks like $\frac1n$. The same three steps prove the law for averages of dice, measurements or anything else with a finite variance, as one of the problems shows. The next lesson takes up a different famous confusion about what new information does and does not change: the Monty Hall problem.

Check yourself

A fair coin has just landed heads six times in a row. Which statement about the next 100 flips is correct?

Problems

The first three apply the inequalities directly. The next three ask you to explain or to test a hypothesis. The last two prove extensions.

Problem 1

A fair coin is flipped 400 times. Use the weak law to bound the probability that the share of heads differs from $\frac12$ by 0.05 or more. In terms of the number of heads, which outcomes does this event contain?

Show solutionHide solution

With $n = 400$ and $\varepsilon = 0.05$ the bound is $\frac{1}{4 \cdot 400 \cdot 0.0025} = \frac14$. A share of heads at least 0.05 from $\frac12$ means at most $0.45 \times 400 = 180$ heads or at least $0.55 \times 400 = 220$ heads. So $P(S \le 180 \text{ or } S \ge 220) \le 0.25$.

Problem 2

The average score on a quiz is 6 points, and no score is negative. (a) At most what fraction of the class scored 9 or more? (b) Give an example of a class in which that fraction is attained. (c) If scores could be negative, would the bound in (a) still hold?

Show solutionHide solution

(a) Choose a student at random and let $Y$ be their score. Then $Y \ge 0$ and $E[Y] = 6$, so by Markov’s inequality $P(Y \ge 9) \le \frac69 = \frac23$. (b) Let two thirds of the class score exactly 9 and one third score 0. The average is $\frac23 \cdot 9 = 6$. (c) No. Let 90% of the class score 9 and 10% score $-21$. The average is $0.9 \cdot 9 - 0.1 \cdot 21 = 6$, and the fraction at 9 or more is $0.9 > \frac23$. A few very negative scores can pay for any number of high ones.

Problem 3

A fair coin has landed heads 10 times in a row. It is flipped 90 more times. Find the probability that the next flip is tails, the expected lead of heads over tails after all 100 flips, and the expected share of heads.

Show solutionHide solution

The next flip is independent of the first ten, so it is tails with probability $\frac12$. The 90 later flips have expected value 45 heads and 45 tails, so the expected totals are 55 heads and 45 tails: an expected lead of 10, unchanged, and an expected share of heads of 0.55.

Problem 4

How many rolls of a fair die does the weak law require so that, with probability at least 0.9, the share of sixes is within 0.01 of $\frac16$?

Show solutionHide solution

Here $p = \frac16$, so $p(1-p) = \frac{5}{36}$, and we need $\frac{p(1-p)}{n\varepsilon^2} \le 0.1$ with $\varepsilon = 0.01$:

$$ n \ge \frac{5/36}{0.0001 \times 0.1} = \frac{5}{36} \times 100{,}000 \approx 13{,}888.9. $$

So $n = 13{,}889$ rolls suffice. Using the cruder bound $\frac{1}{4n\varepsilon^2}$ would demand 25,000; knowing $p$ helps because $p(1-p)$ is well below $\frac14$ when $p$ is far from $\frac12$.

Problem 5

For a fair coin flipped $n$ times, let $D_n$ be heads minus tails. Compute the standard deviation of $D_n$ and of the share of heads for $n = 100$, $n = 10{,}000$ and $n = 1{,}000{,}000$. Explain in a sentence how both columns of your table can be right.

Show solutionHide solution

$D_n = 2S_n - n$ has variance $4 \cdot \frac n4 = n$, so its standard deviation is $\sqrt n$: 10, 100 and 1000. The share $S_n/n$ has variance $\frac{1}{4n}$ and standard deviation $\frac{1}{2\sqrt n}$: 0.05, 0.005 and 0.0005. The share’s deviation from $\frac12$ equals $D_n/(2n)$, and $\sqrt n / (2n) = \frac{1}{2\sqrt n}$: the numerator grows, but a hundred times more flips makes it only ten times larger while the denominator is a hundred times larger.

Problem 6

A machine writes down a sequence of $n$ letters as follows. It flips a fair coin once. On heads it writes H, T, H, T, ... alternating; on tails it writes T, H, T, H, .... For even $n$, find the mean and variance of the share of H’s. Does the conclusion of the weak law hold? Are the hypotheses satisfied?

Show solutionHide solution

For even $n$ both possible sequences contain exactly $\frac n2$ H’s, so the share of H’s is $\frac12$ with certainty: its mean is $\frac12$ and its variance is 0. The conclusion of the weak law holds trivially, since $P(|\text{share} - \frac12| \ge \varepsilon) = 0$. The hypotheses do not hold. Each letter is H with probability $\frac12$, but the letters are completely dependent: the first determines all the rest. So independence is sufficient for the conclusion and not necessary. Compare the copied coin in the lesson, where dependence destroyed the conclusion. Dependence can push the variance of the share either way, and the theorem covers neither case.

Problem 7

Call random variables $U$ and $V$ on a finite sample space independent if $P(U = u \text{ and } V = v) = P(U = u)\,P(V = v)$ for all values $u$ and $v$. (a) Prove that if $U$ and $V$ are independent then $E[UV] = E[U]\,E[V]$. (b) Deduce that $\operatorname{Var}(U + V) = \operatorname{Var}(U) + \operatorname{Var}(V)$ for independent $U$ and $V$. (c) Let $X_1, \dots, X_n$ be random variables, any two of which are independent, with the same mean $\mu$ and variance $\sigma^2$, and let $\bar X = \frac{1}{n}(X_1 + \dots + X_n)$. Show that $P(|\bar X - \mu| \ge \varepsilon) \le \frac{\sigma^2}{n\varepsilon^2}$. (d) Apply (c) to the average of 10,000 rolls of a fair die with $\varepsilon = 0.1$, given that one roll has variance $\frac{35}{12}$.

Show solutionHide solution

(a) Group outcomes by the pair of values $(u, v)$:

$$ E[UV] = \sum_{u, v} uv\,P(U = u, V = v) = \sum_{u, v} uv\,P(U = u)P(V = v) = \Bigl(\sum_u u\,P(U = u)\Bigr)\Bigl(\sum_v v\,P(V = v)\Bigr) = E[U]E[V]. $$

(b) Write $\mu_U, \mu_V$ for the means. The deviation of $U + V$ from its mean is $(U - \mu_U) + (V - \mu_V)$. Squaring and taking expectations,

$$ \operatorname{Var}(U + V) = \operatorname{Var}(U) + \operatorname{Var}(V) + 2E[(U - \mu_U)(V - \mu_V)]. $$

Expanding the last expectation by linearity gives $E[UV] - \mu_U\mu_V - \mu_U\mu_V + \mu_U\mu_V = E[UV] - \mu_U\mu_V$, which is 0 by (a).

(c) Expanding $\bigl(\sum_i (X_i - \mu)\bigr)^2$ produces the squares, whose expectations add to $n\sigma^2$, and cross terms $E[(X_i - \mu)(X_j - \mu)]$ with $i \ne j$, each of which is 0 as in (b). So $\operatorname{Var}(X_1 + \dots + X_n) = n\sigma^2$ and $\operatorname{Var}(\bar X) = \frac{1}{n^2} \cdot n\sigma^2 = \frac{\sigma^2}{n}$. Also $E[\bar X] = \mu$ by linearity. Chebyshev’s inequality with $t = \varepsilon$ gives the bound.

(d) $\frac{35/12}{10{,}000 \times 0.01} = \frac{35}{1200} \approx 0.029$. The average of 10,000 rolls is within 0.1 of 3.5 with probability at least 0.97.

Problem 8

Show that Chebyshev’s inequality cannot be improved in general: for any $t > 0$ and any $q$ with $0 < q \le 1$, find a random variable $X$ for which $P(|X - \mu| \ge t)$ equals $\operatorname{Var}(X)/t^2 = q$ exactly.

Show solutionHide solution

Let $X$ take the value $t$ with probability $\frac q2$, the value $-t$ with probability $\frac q2$, and the value 0 with probability $1 - q$. By symmetry $\mu = 0$. Then $\operatorname{Var}(X) = E[X^2] = t^2 \cdot \frac q2 + t^2 \cdot \frac q2 = qt^2$, so $\operatorname{Var}(X)/t^2 = q$. And $|X - \mu| \ge t$ happens exactly when $X = \pm t$, which has probability $q$. So the two sides are equal. Chebyshev’s bound is loose for the binomial distribution because that distribution has much thinner tails than this three-point example, and the inequality has to cover both.

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)
}

# double hash: std seeded_random is a single sine hash and its draws are overdispersed
let frac = |x| x - floor(x)
let rnd = |i, salt| frac(sin(i * 39.3468 + salt * 11.135 + frac(sin(i * 12.9898 + salt * 78.233) * 43758.5453) * 6.2831853) * 24634.6345)
# flip number i of a simulated fair coin: 1 for heads, 0 for tails
let flip = |i, salt| rnd(i, salt) < 0.5
# pmf[k] = chance of exactly k heads in n fair flips, for k = 0..n
let fair_table = |n| {
    var t = [0.5 ^ n]
    for (k in range(0, n)) {
        t .= t[k] * (n - k) / (k + 1)
    }
    return t
}
# chance that the share of heads in n fair flips is at least n / den away from one half
let outside = |n, den| {
    let t = fair_table(n)
    var s = 0
    for (k in range(0, n + 1)) {
        if (abs(2 * k - n) * den >= 2 * n - 0.000001) {
            s = s + t[k]
        }
    }
    return s
}
let Frac = |num, den, size = 1.0, col = INK| Math(str_join(["\frac{", to_string(num), "}{", to_string(den), "}"]), size, col)