The Normal Distribution & the Central Limit Theorem
Info sheet · Statistics for Psychology & Neuroscience
Author
Andrew Bell
Published
August 13, 2026
Info sheet 0.2 (draft) · Prerequisites: the mean and standard deviation; histograms · Give feedback ↗
Warning✎ Editing notes — to do / to check
Working notes for the author — not shown to students once collapsed; remove before publishing.
[ ]
What you’ll get from this sheet
The bell curve, and the theorem that explains why it’s everywhere. By the end you should be able to:
Read the normal distribution’s equation and its two parameters.
Use the 68–95–99.7 rule.
State the Central Limit Theorem — and see it work on non‑normal data.
A normal distribution is fully described by its mean μ and standard deviation σ; about 68 / 95 / 99.7% of values fall within 1 / 2 / 3 σ of the mean. The Central Limit Theorem says averages of many independent draws tend toward normal whatever the population’s shape, with spread shrinking as σ/√n.
Why the bell curve matters
The normal distribution is the most important in statistics, and not by accident. Many measurements are approximately normal — adult heights, IQ scores, measurement errors — and, more deeply, the Central Limit Theorem guarantees that averages of many independent influences tend toward normality regardless of the shape of the thing being averaged. Since so much of what we measure is the sum of many small causes, the bell curve turns up everywhere.
Its appeal is partly that just two numbers pin it down completely — the mean and the standard deviation. Roughly 68% of values fall within one SD of the mean, 95% within two, 99.7% within three. That “95% within two SDs” is the seed of the confidence intervals and significance thresholds we formalise in Part II.
Two knobs: μ slides the peak left and right, σ sets the width (small σ → tall and narrow; large σ → short and wide). The \(\frac{1}{\sigma\sqrt{2\pi}}\) out front just keeps the total area at 1. Try it:
md`**Mean μ** — currently **${(+mu).toFixed(1)}** · **SD σ** — currently **${(+sig).toFixed(1)}**`
viewof mu =html`<input type="range" min="-5" max="5" step="0.5" value="0" style="width:250px">`viewof sig =html`<input type="range" min="0.5" max="4" step="0.1" value="2" style="width:250px">`
Notice μ only shifts the curve while σ stretches it — but the 68/95/99.7 proportions never change, because they’re defined relative to σ. That scale‑invariance is why we can standardise any normal to a single reference (the z‑distribution).
The Central Limit Theorem
Here’s the deep part. Take any population — skewed, bimodal, lumpy, doesn’t matter — draw a sample of size n, record its mean, and repeat many times. The distribution of those sample means is approximately normal, centred on the population mean, with standard deviation σ/√n. The bigger the sample, the tighter and more bell‑shaped it gets. Pick an ugly population and crank up n:
viewof nn =html`<input type="range" min="1" max="50" step="1" value="5" style="width:340px">`
cltWidget = {let s=99;const rand=()=>{s|=0;s=s+0x6D2B79F5|0;let t=Math.imul(s^s>>>15,1|s);t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296;};const nrm=()=>{const u=1-rand(),v=rand();returnMath.sqrt(-2*Math.log(u))*Math.cos(2*Math.PI*v);};const draw = pop==="unif"? (()=>rand()): pop==="skew"? (()=>-Math.log(1-rand())): (()=>rand()<0.5?2+0.5*nrm() :8+0.5*nrm());const stats = pop==="unif"? {mu:0.5,sd:Math.sqrt(1/12)}: pop==="skew"? {mu:1,sd:1}: {mu:5,sd:Math.sqrt(9.25)};const lo=stats.mu-4*stats.sd, hi=stats.mu+4*stats.sd, bins=40, bw=(hi-lo)/bins;const hist=(data)=>{const c=Array(bins).fill(0); data.forEach(v=>{const b=Math.floor((v-lo)/bw);if(b>=0&&b<bins)c[b]++;});return c;};const raw=[];for(let i=0;i<3000;i++) raw.push(draw());const n=+nn, M=2000, means=[];for(let k=0;k<M;k++){let acc=0;for(let j=0;j<n;j++)acc+=draw();means.push(acc/n);}const hRaw=hist(raw), hMean=hist(means);const W=470,H=300,padL=30,padR=12;const topY=18, topH=64, botY=104, botH=150;const X=x=>padL+(x-lo)/(hi-lo)*(W-padL-padR);const barsTop=(()=>{const mx=Math.max(...hRaw);return hRaw.map((c,i)=>`<rect x="${X(lo+i*bw)}" y="${topY+topH-c/mx*topH}" width="${(W-padL-padR)/bins-1}" height="${c/mx*topH}" fill="#C0501E" fill-opacity="0.55"/>`).join("");})();const seTheory=stats.sd/Math.sqrt(n);const mxM=Math.max(...hMean);const barsBot=hMean.map((c,i)=>`<rect x="${X(lo+i*bw)}" y="${botY+botH-c/mxM*botH}" width="${(W-padL-padR)/bins-1}" height="${c/mxM*botH}" fill="#1F4E79" fill-opacity="0.7"/>`).join("");// normal overlay for the means: mean=mu, sd=seTheory, scaled to histogram peakconst npdf=x=>Math.exp(-((x-stats.mu)**2)/(2*seTheory*seTheory))/(seTheory*Math.sqrt(2*Math.PI));const peak=npdf(stats.mu);let np=[];for(let x=lo;x<=hi;x+=(hi-lo)/200) np.push(`${X(x)}${botY+botH-npdf(x)/peak*botH}`);const overlay=`<path d="M ${np.join(" L ")}" fill="none" stroke="#1E7A34" stroke-width="2"/>`;const fig=document.createElement("figure"); fig.style.margin="0"; fig.innerHTML=`<svg viewBox="0 0 ${W}${H}" width="${Math.min(W,540)}" style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px">`+`<text x="${padL}" y="12" font-size="11" fill="#C0501E">the population (single draws) — n = 1</text>${barsTop}`+`<text x="${padL}" y="${botY-4}" font-size="11" fill="#1F4E79">distribution of the sample mean — n = ${n}</text>${barsBot}${overlay}`+`</svg>`+`<figcaption style="margin-top:.5rem">Population mean μ = ${stats.mu.toFixed(2)}. Predicted spread of the mean = σ/√n = ${stats.sd.toFixed(2)}/√${n} = <b>${seTheory.toFixed(3)}</b>. `+`The <span style="color:#1E7A34">green curve</span> is the normal the CLT predicts — the blue histogram matches it even though the population (orange) isn't normal.</figcaption>`;return fig;}
Watch what happens as you raise n. At n = 1 the “means” are just the raw population — as skewed or lumpy as ever. But even at n = 5 the histogram already leans bell‑shaped, and by n = 30 it’s an almost perfect normal, hugging the green CLT curve and shrinking toward the population mean. The population’s shape stops mattering; only its mean and its σ/√n survive. That is why the normal distribution underwrites so much of statistics — every time we work with a sample mean, the CLT hands us a bell curve.
x=-4:0.01:4;plot(x,normpdf(x,0,1));% the bell curvemeans=mean(exprnd(1,30,2000));% 2000 sample means, n = 30histogram(means); [std(means),1/sqrt(30)] % observed vs theoretical SE
The R and Python tabs run live; MATLAB is a static reference.
TipCheck your understanding
A population is heavily skewed. You take many samples of size 40 and record each sample’s mean. What will the distribution of those means look like?
Approximately normal — centred on the population mean, with standard deviation σ/√40 (about one‑sixth of the population’s σ). That’s the Central Limit Theorem: the distribution of the sample mean tends to normal regardless of the population’s shape, provided the population has finite variance and n is large enough. The raw data stay skewed; only their averages go bell‑shaped.
The CLT is about the distribution of the mean (or sum), not the raw observations — individual data points stay exactly as skewed as they were; only their averages normalise. It also needs finite variance and a “large enough” n, and the messier (more skewed) the population, the bigger n has to be before the approximation is good. And the 68–95–99.7 rule only applies to data that are actually normal — don’t assume it for arbitrary distributions.
Where this shows up next
The “95% within 2σ” idea becomes confidence intervals and p‑values in Part II. See Chapter (Foundations) for the full treatment, and the When Data Aren’t Normal sheet for what to do when the bell curve doesn’t fit.
Related topics
Describing Data — the mean and SD that parameterise the curve.