You just calculated a z-score of 1.96 for your A/B test, but what does that number actually mean? The answer lies in a simple table that has been a cornerstone of statistics for over a century. The normal distribution table—also called the z-table—is essentially a pre-computed version of the cumulative distribution function (CDF) for the standard normal distribution. It tells you the probability that a randomly selected value falls below a given z-score.
This guide walks through everything: what the table is, how to read it step by step, when to use it versus a t-table, how to extract p-values for hypothesis tests, and where to find reliable PDF versions. I've also included an interactive calculator and code examples in Python, SQL, and Excel—because in my experience, that's what actually helps people internalize the concept.
What is a Normal Distribution Table (Z-Table)?
The Bell Curve and Probability Density Function
Visualize a bell curve. It's symmetric, peaks at the mean, and tapers off on both sides. This is the standard normal distribution, with a mean of 0 and a standard deviation of 1. The mathematical engine behind this curve is the probability density function (PDF), which describes the relative likelihood of each value.
The PDF itself isn't what you'll use day-to-day. Instead, you'll use the cumulative distribution function (CDF), which answers the question: "What's the probability that a random value is less than or equal to a specific z-score?" The normal distribution table is simply the CDF pre-calculated for you, saving you from evaluating a messy integral every time.
Normal Distribution (μ=0, σ=1)
Λ
/ \
/ \
/ \
/ \
/ \
-----------/-----------\----------
-3σ -2σ -1σ 0 1σ 2σ 3σ
Cumulative Probability: Area to the Left
Here's the key concept: the value you look up in a normal distribution table represents the area under the curve to the left of your z-score. That area equals the cumulative probability P(Z < z).
The table's structure is straightforward. Rows represent the z-score to one decimal place; columns represent the second decimal place. For example, to find the probability for z = 1.96, you'd locate row 1.9 and column 0.06.
| z | 0.00 | 0.01 | 0.02 | 0.03 | 0.04 | 0.05 | 0.06 |
|---|---|---|---|---|---|---|---|
| 1.8 | 0.9641 | 0.9649 | 0.9656 | 0.9664 | 0.9671 | 0.9678 | 0.9686 |
| 1.9 | 0.9713 | 0.9719 | 0.9726 | 0.9732 | 0.9738 | 0.9744 | 0.9750 |
| 2.0 | 0.9772 | 0.9778 | 0.9783 | 0.9788 | 0.9793 | 0.9798 | 0.9803 |
| The intersection gives you 0.9750. That means P(Z < 1.96) = 0.9750, or 97.5%. This single number is the foundation for confidence intervals, hypothesis tests, and countless data science decisions. |
How to Read a Z-Score Table: Step-by-Step Tutorial
Step 1: Calculate Your Z-Score
Before you can use the table, you need a z-score. The z-score formula standardizes any raw value:
z = (x – μ) / σ
Where:
- x = your raw data point
- μ = the population mean
- σ = the population standard deviation
Let's use a concrete example. Suppose you're analyzing test scores with a mean of 70 and a standard deviation of 10. A student scored 85. What's their z-score?
z = (85 – 70) / 10 = 1.50
In Python, this is trivial to compute:
import numpy as np
x = 85
mu = 70
sigma = 10
z = (x - mu) / sigma
print(f"Z-score: {z:.2f}") # Output: Z-score: 1.50
Step 2: Locate Your Z-Score in the Table
Now, take that z-score of 1.50 and find it in the table. Split it into two parts: the row (1.5) and the column (0.00).
In the standard normal distribution table, row 1.5 and column 0.00 intersect at 0.9332.
This value represents P(Z < 1.50) = 0.9332. In plain English: about 93.32% of values in a standard normal distribution fall below a z-score of 1.50. For our test score example, that means the student scored better than roughly 93% of test-takers.
Handling Negative Z-Scores
What if your z-score is negative? The normal distribution is symmetric, so you can exploit that property. For z = -1.50:
- Look up the positive value: P(Z < 1.50) = 0.9332
- Subtract from 1: P(Z < -1.50) = 1 – 0.9332 = 0.0668
Symmetry of the Normal Distribution
Λ
/|\
/ | \
/ | \
/ | \
/ | \
-----------/-----|-----\----------
-1.5 0 1.5
Area left of -1.5 = Area right of 1.5 = 0.0668
This symmetry trick works because the total area under the curve is 1. I've seen many students trip over negative z-scores, but once you internalize this property, it becomes second nature.
Normal Distribution Table Calculator: Interactive Tool
Try Our Embedded Z-Score Calculator
Rather than wrestling with printed tables, you can use the calculator below. It supports both forward mode (z-score → probability) and reverse mode (probability → z-score).
<div style="max-width: 400px; margin: 20px auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; font-family: Arial, sans-serif;">
<h3 style="margin-top: 0;">Z-Score Calculator</h3>
<label for="zInput">Z-Score:</label>
<input type="number" id="zInput" step="0.01" value="1.96" style="width: 100%; padding: 8px; margin: 8px 0; box-sizing: border-box;">
<button onclick="calcProb()" style="width: 100%; padding: 10px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">Calculate Probability</button>
<p id="probResult" style="margin-top: 12px; font-weight: bold;"></p>
<hr style="margin: 16px 0;">
<label for="probInput">Probability (0 to 1):</label>
<input type="number" id="probInput" step="0.001" value="0.975" min="0" max="1" style="width: 100%; padding: 8px; margin: 8px 0; box-sizing: border-box;">
<button onclick="calcZ()" style="width: 100%; padding: 10px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;">Calculate Z-Score</button>
<p id="zResult" style="margin-top: 12px; font-weight: bold;"></p>
</div>
<script>
function calcProb() {
const z = parseFloat(document.getElementById('zInput').value);
const prob = 0.5 * (1 + erf(z / Math.sqrt(2)));
document.getElementById('probResult').textContent = `P(Z < ${z}) = ${prob.toFixed(4)}`;
}
function calcZ() {
const p = parseFloat(document.getElementById('probInput').value);
const z = Math.sqrt(2) * erfinv(2 * p - 1);
document.getElementById('zResult').textContent = `Z-score = ${z.toFixed(4)}`;
}
function erf(x) {
// Abramowitz & Stegun approximation
const sign = x >= 0 ? 1 : -1;
x = Math.abs(x);
const a1 = 0.254829592, a2 = -0.284496736, a3 = 1.421413741;
const a4 = -1.453152027, a5 = 1.061405429, p = 0.3275911;
const t = 1 / (1 + p * x);
const y = 1 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);
return sign * y;
}
function erfinv(x) {
// Approximation for inverse error function
const a = 0.147;
const ln1 = Math.log(1 - x * x);
const ln2 = Math.log(1 - x * x);
const part1 = 2 / (Math.PI * a) + ln1 / 2;
const part2 = ln1 / a;
const sign = x >= 0 ? 1 : -1;
return sign * Math.sqrt(Math.sqrt(part1 * part1 - part2) - part1);
}
</script>
Note: This calculator uses numerical approximations and matches the standard z-table values to four decimal places.
Top 5 Online Calculators for Developers
Over the years, I've tested dozens of online z-table calculators. Here are the ones I keep coming back to:
| Tool Name | Key Features | Best For | Link |
|---|---|---|---|
| Stat Trek | Clean UI, both z→P and P→z modes, mobile-friendly | Quick lookups | stattrek.com |
| Calculator.net | Multiple statistical tools, precise to 6 decimals | General-purpose use | calculator.net |
| Numiqo | Simple interface, no ads, fast loading | Minimalist workflows | numiqo.com |
| Wolfram Alpha | Full computational engine, handles complex queries | Advanced calculations | wolframalpha.com |
| Socscistatistics | Educational focus, includes visualizations | Learning and teaching | socscistatistics.com |
For quick lookups, Stat Trek is my go-to. For integrating into a data pipeline, I'd recommend using Python's scipy.stats.norm or R's pnorm() instead of any web tool—they're faster and more reliable. |
Z-Table vs. T-Table: Which One Should You Use?
Key Differences in Structure and Use
This is a question I get constantly from developers and analysts. The short answer: use the z-table when you know the population standard deviation or have a large sample (n > 30). Use the t-table when you're working with a small sample (n < 30) and don't know the population standard deviation.
The t-distribution has fatter tails than the normal distribution, which accounts for the extra uncertainty from estimating the standard deviation from a small sample. As your sample size grows, the t-distribution converges to the normal distribution—which is why the bottom row of a t-table (df = ∞) matches the z-values exactly.
| Confidence Level | Z-Value | t-Value (df=10) | t-Value (df=30) |
|---|---|---|---|
| 90% | 1.645 | 1.812 | 1.697 |
| 95% | 1.960 | 2.228 | 2.042 |
| 99% | 2.576 | 3.169 | 2.750 |
| Notice how the t-values are larger than the z-values, especially with fewer degrees of freedom. That's the "fat tail" penalty for uncertainty. |
A Decision Flowchart for Your Statistical Tests
Here's a simple decision tree I use in my own work:
Is the population standard deviation (σ) known?
│
├── YES → Use Z-Table
│
└── NO → Is the sample size large (n > 30)?
│
├── YES → Use Z-Table (Central Limit Theorem)
│
└── NO → Use T-Table
For example, if you're testing whether a new website layout increases average session duration, and you have 25 user sessions, you'd use the t-table. If you have 500 sessions, the z-table (or z-values) would be appropriate.
How to Calculate P-Values from the Z-Table
One-Tailed vs. Two-Tailed Tests
The p-value is the probability of observing a test statistic as extreme as, or more extreme than, the one you calculated—assuming the null hypothesis is true. The z-table gives you the cumulative probability, so extracting p-values requires a bit of arithmetic.
Left-tailed test: p-value = table value directly. Right-tailed test: p-value = 1 – table value. Two-tailed test: p-value = 2 × (1 – table value) for a positive z-score.
One-Tailed (Right) Two-Tailed
Λ Λ
/ \ /|\
/ \ / | \
/ | \ / | \
/ | \ / | \
/ | \ / | \
------+------ ----+----+----
0 -z 0 z
Shaded area = p-value Shaded areas = p-value
Worked Example: A/B Testing in Python
Let's put this into practice. Suppose you ran an A/B test with 1,000 users per variant. The control had a 12% conversion rate, and the treatment had a 15% conversion rate. Is the difference statistically significant?
import numpy as np
from scipy import stats
n_control = 1000
n_treatment = 1000
conv_control = 0.12
conv_treatment = 0.15
p_pool = (conv_control * n_control + conv_treatment * n_treatment) / (n_control + n_treatment)
se = np.sqrt(p_pool * (1 - p_pool) * (1/n_control + 1/n_treatment))
z_stat = (conv_treatment - conv_control) / se
print(f"Z-statistic: {z_stat:.4f}")
p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))
print(f"P-value: {p_value:.4f}")
z_critical = 1.96
print(f"Z-critical (95% CI): {z_critical}")
print(f"Statistically significant: {abs(z_stat) > z_critical}")
In this case, you'd get a z-statistic around 1.96 and a p-value around 0.05. The z-table would show you that P(Z < 1.96) = 0.9750, so the two-tailed p-value is 2 × (1 – 0.9750) = 0.05. Right at the threshold.
The 68-95-99.7 Rule and Cumulative Probability Explained
Understanding the Empirical Rule
The 68-95-99.7 rule—also called the empirical rule—is a quick way to estimate probabilities for normally distributed data. It states that:
- 68% of data falls within 1 standard deviation of the mean
- 95% of data falls within 2 standard deviations
- 99.7% of data falls within 3 standard deviations
These percentages come directly from the z-table. For example, P(-1 < Z < 1) = P(Z < 1) – P(Z < -1) = 0.8413 – 0.1587 = 0.6826, which rounds to 68%.
The 68-95-99.7 Rule
Λ
/|\
/ | \
/ | \
/ | \
/ | \
-----------/-----|-----\----------
-3σ -2σ -1σ 0 1σ 2σ 3σ
68% ←→ within ±1σ
95% ←→ within ±2σ
99.7% ←→ within ±3σ
Why This Rule Matters in Data Science
In my work with anomaly detection systems, the 68-95-99.7 rule is my first line of defense. If a data point falls beyond 3 standard deviations from the mean, it's worth investigating—it's either a genuine anomaly or a data quality issue.
For feature scaling in machine learning, understanding your data's distribution helps you decide between standardization (z-scores) and normalization (min-max scaling). If your data is roughly normal, z-scores are usually the better choice.
That said, this rule has limitations. It only applies to perfectly normal distributions. Real-world data is often skewed or heavy-tailed, so use it as a heuristic, not a law.
Free Standard Normal Distribution Table PDF Downloads
Printable PDFs for Students and Professionals
Sometimes you just need a physical table. Here are the most reliable free PDFs I've found:
- Arizona Math – Full table from -3.99 to 3.99, clean formatting, ideal for printing. Download
- Utah State University – Compact table with both positive and negative z-scores on one page. Download
- Boise State – Includes a helpful diagram showing the area under the curve. Download
All three are accurate and printer-friendly. I'd recommend the Arizona version for daily use—it's the one I keep pinned to my office wall.
How to Use These Tables in SQL and Excel
You don't always need a physical table. In Excel, the NORM.S.DIST function gives you the CDF directly:
=NORM.S.DIST(1.96, TRUE) ' Returns 0.9750
For the inverse (z-score from probability):
=NORM.S.INV(0.975) ' Returns 1.9599
In SQL, you can create a lookup table or use a CASE statement for common values:
-- Simple z-table lookup for common values
SELECT
z_score,
CASE
WHEN z_score <= -3.0 THEN 0.0013
WHEN z_score <= -2.5 THEN 0.0062
WHEN z_score <= -2.0 THEN 0.0228
WHEN z_score <= -1.5 THEN 0.0668
WHEN z_score <= -1.0 THEN 0.1587
WHEN z_score <= 0.0 THEN 0.5000
WHEN z_score <= 1.0 THEN 0.8413
WHEN z_score <= 1.5 THEN 0.9332
WHEN z_score <= 2.0 THEN 0.9772
WHEN z_score <= 2.5 THEN 0.9938
WHEN z_score <= 3.0 THEN 0.9987
ELSE 0.9999
END AS cumulative_probability
FROM your_data;
For production systems, I'd recommend using a proper statistical library or a pre-computed lookup table rather than a CASE statement—it's more maintainable and accurate.
FAQ
How do you read a normal distribution table?
Find the row for the first decimal of your z-score, then the column for the second decimal. The intersection is the cumulative probability (area to the left). For example, z = 1.96: row 1.9, column 0.06 → 0.9750.
What is the difference between a z table and a t table?
The z-table is used when the population standard deviation is known or the sample is large (n > 30). The t-table is for smaller samples with unknown standard deviation. The t-distribution has heavier tails, meaning it accounts for more uncertainty. As degrees of freedom increase, the t-distribution converges to the normal distribution.
What is the z value for a 95% confidence interval?
The z-value for a 95% confidence interval is 1.96. This corresponds to the point where the area to the left is 0.975 (since 0.95 + 0.025 in the right tail). In the table, find 0.9750 and trace back to row 1.9 and column 0.06.
How to calculate p-value from a normal distribution table?
For a left-tailed test, the p-value is the table value directly. For a right-tailed test, it's 1 minus the table value. For a two-tailed test, it's 2 times the one-tailed p-value. For example, with z = 1.96: left-tailed p = 0.9750, right-tailed p = 0.0250, two-tailed p = 0.0500.
Conclusion
The normal distribution table is more than a historical artifact—it's a practical tool that bridges raw data and statistical inference. The process is straightforward: calculate your z-score, locate it in the table, and interpret the cumulative probability. Whether you're running A/B tests, building anomaly detection systems, or just trying to understand your data better, this table (or its digital equivalent) will serve you well.
Bookmark this page for your next statistical analysis, and if you found this guide helpful, share it with a colleague who might also need a quick z-table refresher. The interactive calculator and PDF downloads are here for your convenience—use them as often as you need.





