Chapter 6 · Part 3
Capstone: estimate π
Time to use everything at once on something genuinely fun: estimating π by throwing random darts. It's a Monte Carlo simulation — solving a math problem with randomness — and it touches every skill from this course: array creation, math, boolean masks and aggregation.
The idea
Picture a 1×1 square with a quarter-circle of radius 1 drawn inside it. The square has area
1; the quarter-circle has area π/4. So if you scatter random points across the square, the
fraction that land inside the circle is about π/4 — which means:
The whole thing, vectorized
No loops. We generate all the points at once, test them all at once with a boolean mask, and average:
import numpy as np
rng = np.random.default_rng(42)
n = 1_000_000
points = rng.random((n, 2)) # n random (x, y) in the unit square
inside = points[:, 0]**2 + points[:, 1]**2 <= 1.0 # boolean mask: inside the circle?
pi = 4 * inside.mean() # fraction inside, times 4
print(f"pi is about {pi:.4f}")pi is about 3.1422Read what each line does — it's the whole course in four lines: rng.random((n, 2)) creates
an array, **2 and + are vectorized math, <= 1.0 is a boolean mask, and .mean()
is an aggregation. inside.mean() works because True counts as 1 and False as 0, so
the mean is the fraction that landed inside.
More darts, better estimate
The beauty of Monte Carlo: throw more darts, get closer to the truth. Try a ladder of sizes:
for n in [1_000, 10_000, 100_000, 1_000_000]:
points = rng.random((n, 2))
inside = points[:, 0]**2 + points[:, 1]**2 <= 1.0
print(f"n={n:>9,} pi ~ {4 * inside.mean():.4f}")n= 1,000 pi ~ 3.0840
n= 10,000 pi ~ 3.1584
n= 100,000 pi ~ 3.1470
n=1,000,000 pi ~ 3.1422Watch the error shrink — off by 0.058, then 0.017, 0.005, 0.0006. Because it's random,
any single run wobbles, but on average more darts means a tighter estimate. You just approximated
one of math's most famous constants with a boolean mask and a mean.
Where NumPy goes from here
That four-line simulation is the same shape as serious scientific computing — generate data, transform it with vectorized math, reduce it to an answer. From here:
- pandas builds spreadsheet-like tables on top of NumPy arrays — the next step for real data.
- Matplotlib plots arrays; try scattering your dart points colored by inside/outside.
- The rest of this track uses NumPy everywhere: it's the retriever's math in Semantic Search, and it is the whole engine in A Neural Net From Scratch, where these same operations — matrix math, masks, reshaping — train a real network.
You didn't just read about NumPy — you indexed, broadcast, aggregated and simulated your way through it. Every data and AI tool you pick up next will feel a little more familiar.