Skip to content
Vamshi Jandhyala

Mathematics

A Hundred Random Chords

PDF

The June 2026 MoMath Monthly Mindbender: 100 chords are drawn on a circle, each joining two independent uniform points on the circumference. Two random chords cross with probability 1/3, so the expected number of intersection points is 4950/3 = 1650. The same count fixes the variance, 22660, and the expected number of regions the disc is cut into, exactly 1751.

Problem

Choose a point uniformly at random on a circle, choose a second the same way, and join them with a chord. Do this 100 times, giving 100 random chords. What is the expected number of intersection points?

Credit: MoMath Monthly Mindbenders, June 2026.

When do two chords cross?

Everything rests on one question: what is the chance that two random chords cross? A chord pair involves four independent uniform points on the circle, all distinct with probability 11. Condition on where the four points sit and forget which is which. By exchangeability, every assignment of the four positions to the four labels is equally likely, so the two points forming the first chord are equally likely to be any of the three ways of splitting the four positions into two pairs. Walking round the circle through positions 1,2,3,41, 2, 3, 4, the three splittings pair the positions as 123412|34, 142314|23, and 132413|24, and only the last, the interleaved one, makes the chords cross. Hence

P(two random chords cross)=13.\mathbb{P}(\text{two random chords cross}) = \frac13.

A second route gives the same number and will earn its keep shortly. The first chord’s endpoints cut the circumference into two arcs, and the fraction tt of the circle on one side is uniform on (0,1)(0,1). The second chord crosses the first exactly when its two endpoints land on opposite sides, which given tt has probability 2t(1t)2t(1-t), and

012t(1t)dt=13.\int_0^1 2t(1-t)\,dt = \frac13.

The count

The rest is linearity of expectation. With probability 11 no two chords share an endpoint and no three pass through a common point, so the intersection points are exactly the crossing pairs of chords, and the pairs are (1002)=4950\binom{100}{2} = 4950 in number. Each crosses with probability 13\tfrac13, and expectations add whether or not the events are independent (they are not), so the expected number of intersection points is

(1002)13=49503=1650.\binom{100}{2}\cdot\frac13 = \frac{4950}{3} = 1650.

In general, nn random chords produce n(n1)/6n(n-1)/6 crossings on average.

Two panels. On the left, a circle criss-crossed by one hundred faint blue chords, with every crossing point marked as a small copper dot; the dots number 1684 in this particular draw and fill the disc fairly evenly, thinning slightly towards the rim. On the right, a histogram of the number of crossings over fifty thousand simulated draws, in pale copper bars, running from about 1150 to about 2200 and peaking near 1650. A solid copper curve traces the normal density with mean 1650 and standard deviation 150.5, matching the bars closely, and a dashed vertical line marks the mean at 1650.
Left: one draw of $100$ random chords; this one happens to have $1684$ crossings. Right: the crossing count over $50{,}000$ draws, hugging the normal curve with mean $1650$ and standard deviation $150.5$.

How much does it fluctuate?

The mean needed no thought about dependence, but the spread does. Write X=pIpX = \sum_{p} I_p, the sum over the 49504950 chord pairs of the indicator that the pair crosses. Each indicator has variance 1323=29\tfrac13\cdot\tfrac23 = \tfrac29. Two pairs with no chord in common involve eight independent points, so their indicators are independent and contribute nothing. The interesting case is two pairs sharing a chord, say {i,j}\{i,j\} and {i,k}\{i,k\}: given the common chord’s arc fraction tt, the other two chords cross it independently, each with probability 2t(1t)2t(1-t), so

P(both cross)=01(2t(1t))2dt=215,Cov=21519=145.\mathbb{P}(\text{both cross}) = \int_0^1 \bigl(2t(1-t)\bigr)^2\,dt = \frac{2}{15}, \qquad \operatorname{Cov} = \frac{2}{15} - \frac19 = \frac{1}{45}.

The covariance is positive: a chord that cuts near-diametrically across the circle is easy to cross, and one that hugs the rim is hard, so crossings sharing a chord rise and fall together. There are n(n1)(n2)n(n-1)(n-2) ordered pairs of pairs with a common chord, and altogether

Var(X)=(n2)29+n(n1)(n2)145  =n=100  1100+21560=22660,\operatorname{Var}(X) = \binom{n}{2}\frac29 + n(n-1)(n-2)\,\frac{1}{45} \;\stackrel{n=100}{=}\; 1100 + 21560 = 22660,

a standard deviation of 22660150.5\sqrt{22660} \approx 150.5. The shared-chord terms dominate the variance twenty to one, yet the count still behaves like a textbook normal, as the histogram shows.

A remark on regions

The crossing count is doing more work than it appears to. Draw the chords one at a time: a new chord that meets cc of the earlier ones passes through c+1c+1 of the existing regions and splits each, adding c+1c + 1 regions. Starting from one region and summing, the disc ends up cut into exactly 1+n+X1 + n + X pieces. So the expected number of regions the 100100 chords carve the disc into is

1+100+1650=1751,1 + 100 + 1650 = 1751,

an exact consequence of the count just computed, not a separate calculation.

Checking it

The check replays the construction with no shortcuts: draw the endpoint angles, test every pair of chords for interleaving, and count. The pair test also confirms the two probabilities the derivation leans on, 13\tfrac13 for one crossing and 215\tfrac{2}{15} for two crossings of a shared chord.

import numpy as np
rng = np.random.default_rng(7)
n, T, C = 100, 50_000, 100                     # chords, trials, chunk
iu = np.triu_indices(n, 1)
counts = []
for _ in range(T // C):
    th = rng.random((C, n, 2))                 # endpoint angles (turns)
    a, b = th[..., 0], th[..., 1]
    L = (b - a) % 1.0                          # arc from a round to b
    p = (a[:, None, :] - a[:, :, None]) % 1.0  # j's endpoints seen from a_i
    q = (b[:, None, :] - a[:, :, None]) % 1.0
    cross = (p < L[:, :, None]) ^ (q < L[:, :, None])
    counts.append(cross[:, iu[0], iu[1]].sum(axis=1))
X = np.concatenate(counts)
print(f"mean {X.mean():.2f}   (theory {100*99/6:.0f})")
print(f"var  {X.var():.0f}    (theory {100*99/9 + 100*99*98/45:.0f})")
print(f"sd   {X.std():.1f}    (theory {np.sqrt(100*99/9 + 100*99*98/45):.1f})")
# pairwise checks: P(cross) = 1/3, P(two chords both cross a third) = 2/15
th = rng.random((2_000_000, 3, 2)); a, b = th[..., 0], th[..., 1]
L0 = (b[:, 0] - a[:, 0]) % 1.0
def crosses(k):
    pk = (a[:, k] - a[:, 0]) % 1.0; qk = (b[:, k] - a[:, 0]) % 1.0
    return (pk < L0) ^ (qk < L0)
c1, c2 = crosses(1), crosses(2)
print(f"P(cross) {c1.mean():.5f} (1/3 = {1/3:.5f});  "
      f"P(both cross same chord) {np.mean(c1 & c2):.5f} (2/15 = {2/15:.5f})")
# mean 1648.71   (theory 1650)
# var  22698    (theory 22660)
# sd   150.7    (theory 150.5)
# P(cross) 0.33276 (1/3 = 0.33333);  P(both cross same chord) 0.13302 (2/15 = 0.13333)