DEV Community

Alan Matthew
Alan Matthew

Posted on

How to Calculate a Confidence Interval for the Mean (z vs t, With a Worked Example)

Confidence intervals show up in A/B test reports, ML evaluation, and survey dashboards, and they are misread constantly. This post covers how a confidence interval for a mean works, when to use z vs t, and how to verify your numbers in code.

I also maintain a free calculator that shows every step, linked at the end.

What a confidence interval for the mean tells you

You have a sample, not the whole population. The sample mean is your best point estimate, but it carries uncertainty. A confidence interval wraps that estimate in a range:

CI = x̄ ± E
Enter fullscreen mode Exit fullscreen mode

where E is the margin of error.

z-interval vs t-interval

Population σ known (or n is large) → z-interval:

CI = x̄ ± z(α/2) · σ/√n
Enter fullscreen mode Exit fullscreen mode

Population σ unknown (the usual case) → t-interval:

CI = x̄ ± t(α/2, n−1) · s/√n
Enter fullscreen mode Exit fullscreen mode
  • x̄ = sample mean
  • s = sample standard deviation (divide by n−1, not n)
  • s/√n = standard error
  • n−1 = degrees of freedom

The t-distribution has heavier tails, which compensates for estimating σ from a small sample. As n grows, t converges to z.

Common z critical values:

Confidence z critical
90% 1.645
95% 1.960
99% 2.576

Worked example

Resting heart rate (bpm) for 8 adults: 72, 68, 75, 70, 74, 71, 69, 73. We want a 95% CI. σ is unknown, so we use t.

  1. Mean: 572 / 8 = 71.5
  2. Sum of squared deviations: 42.00
  3. Sample SD: √(42 / 7) = √6 = 2.4495
  4. Standard error: 2.4495 / √8 = 0.8660
  5. Critical value: t(0.025, df=7) = 2.3646
  6. Margin of error: 2.3646 × 0.8660 = 2.0477
  7. Interval: 71.5 ± 2.0477 → (69.4523, 73.5477)

Verify it in Python

import numpy as np
from scipy import stats

data = np.array([72, 68, 75, 70, 74, 71, 69, 73])

mean = data.mean()
sem = stats.sem(data)  # uses ddof=1 by default

low, high = stats.t.interval(0.95, df=len(data) - 1, loc=mean, scale=sem)
print(f"95% CI: ({low:.4f}, {high:.4f})")
# 95% CI: (69.4523, 73.5477)
Enter fullscreen mode Exit fullscreen mode

Other tools:

  • Excel: =CONFIDENCE.T(alpha, standard_dev, size) returns the margin of error
  • R: t.test(x, conf.level = 0.95)$conf.int

What moves the margin of error

  • Sample size: E scales with 1/√n, so quadrupling n halves the margin of error.
  • Variability: noisier data means a wider interval.
  • Confidence level: 99% is wider than 95%. You trade precision for certainty.

Common mistakes

  1. Using z when σ is unknown. This understates the margin of error, especially for small samples.
  2. Misreading "95%". It does not mean there's a 95% chance the true mean is inside this specific interval. It means that if you repeated the sampling many times, about 95% of the intervals built this way would contain the true mean.
  3. Dividing by n instead of n−1 when computing the sample SD.
  4. Ignoring assumptions. For small n, the data should be roughly normal. If it clearly isn't, consider bootstrapping.

Try it without writing code

I built a free calculator that takes raw data or summary stats, supports z and t intervals at 90/95/99%, and shows the standard error, critical value, margin of error and the full step-by-step LaTeX working:

👉 Confidence Interval Calculator for Mean

Paste in the heart-rate data from the example above and you should get the same interval as the Python snippet.

If you spot a bug or want another test added (t-tests, ANOVA, non-parametric), let me know in the comments.

Top comments (0)