All labs

Floating Point Has Edges

Compute a variance three algebraically identical ways and watch one of them return a negative number.

Ch 1 1.6
Misconception
Foundations & Data Quality
15 mindifficulty 2/5

Controls

500
6

Every value sits near μ = 1e+6, while the spread stays σ = 1.

1
Working precision
Show Welford

The stable one-pass update.

Random seed

Every result on this page is a deterministic function of the seed and the controls.

Relative error of the variance, as the data moves away from zero

Vertical axis is log₁₀ of the relative error against a double-precision two-pass reference.

-15-10-5002468100% errormachine εlog₁₀ of the data's locationlog₁₀ relative error
naive Σx² − (Σx)²/ntwo-passWelford

This sample, three algorithms

n = 500, μ ≈ 1e+6, working in float32.

Reference σ²
1.0323
double, two-pass
Naive one-pass
-3.77e+6
negative variance!
Two-pass
1.0345
rel. error 2.1e-3
Welford
19.9030
rel. error 1.8e+1

Addition is not associative

Σ 1/i for i = 1 … 10000, same terms, three orders.

ascending9.787612915
descending9.787604332
Kahan compensated9.787606239
double reference9.787606036

Descending order adds the small terms first, while they can still change the running total. Kahan carries the lost low-order bits forward explicitly.

The edges of the number line

0.1 + 0.20.300000000000000044
0.1 + 0.2 === 0.3false
machine ε1.192e-7
(1 + ε/2) − 11.192e-7
largest exact integer2²⁴ = 16777216

Compare floating-point numbers with a tolerance, never with equality.

A negative variance is not a bug in your data

When the naive formula reports a negative σ², nothing about the data is wrong. Σx² and (Σx)²/n are two nearly equal enormous numbers, and their difference keeps only the few bits that survived cancellation. The fix is the algorithm, not the dataset.