Floating Point Arithmetic and IEEE 754

⚡ Key Takeaways

Floating point arithmetic represents real numbers in a finite computer word using a sign, a scaled significand, and an exponent — trading exact representation for enormous dynamic range. The IEEE 754 standard (1985, revised 2008/2019) fixes the bit layouts, rounding rules, and special values (±0, ±∞, NaN) used by essentially every modern processor. It applies everywhere numbers are computed: graphics, simulation, finance, machine learning, embedded control. Key fact: most decimal fractions (even 0.1) are not exactly representable in binary floating point.

💡 The Core Insight

Floating point keeps a constant number of significant digits, not a constant absolute precision. Because the exponent slides the binary point, the spacing between representable numbers grows with magnitude — the gaps double each time you cross a power of two. The fundamental guarantee is therefore not "small absolute error" but "small relative error": every real number in range is approximated to within a fixed fraction uu (the unit roundoff). All of numerical analysis flows from this single bound.

Formal Statement

DefinitionNormalized Floating Point Number

A floating point number system F(β,p,emin⁡,emax⁡)F(\beta, p, e_{\min}, e_{\max}) consists of numbers of the form

1
x=(−1)s×(d0.d1d2⋯dp−1)β×βe\quad x = (-1)^s \times \left( d_0 . d_1 d_2 \cdots d_{p-1} \right)_\beta \times \beta^{e}

where:

  • s∈{0,1}s \in \{0,1\} is the sign bit,
  • β\beta is the radix (base), β=2\beta = 2 in IEEE 754,
  • pp is the precision (number of significand digits did_i, with 0≤di<β0 \le d_i < \beta),
  • ee is the exponent, emin⁡≤e≤emax⁡e_{\min} \le e \le e_{\max},
  • the value is normalized when d0≠0d_0 \ne 0 (for β=2\beta=2, this forces d0=1d_0 = 1).

Derivation hint: the significand 1.d1⋯dp−11.d_1\cdots d_{p-1} lies in [1,2)[1,2); multiplying by 2e2^e rescales it to any binade.

DefinitionIEEE 754 Bit Encoding

A binary IEEE 754 value packs three fields into a word: sign SS (1 bit), biased exponent EE (width ww bits), and trailing significand TT (width t=p−1t = p-1 bits). The stored exponent is biased: E=e+biasE = e + \text{bias}, with bias=2w−1−1\text{bias} = 2^{w-1}-1. The decoded value for a normal number is

2
x=(−1)S×(1+T⋅2−t)×2 E−bias\quad x = (-1)^S \times \left(1 + T \cdot 2^{-t}\right) \times 2^{\,E - \text{bias}}

The leading 1 is the hidden bit — not stored, recovered for free in binary. Derivation hint: TT is the integer formed by the fraction bits; dividing by 2t2^t places the binary point just after the implicit leading 1.

Formattotal bitsww (exp)tt (frac)ppbiasu=2−pu = 2^{-p}
binary16 (half)1651011152−112^{-11}
binary32 (single)32823241272−242^{-24}
binary64 (double)6411525310232−532^{-53}
binary128 (quad)12815112113163832−1132^{-113}
DefinitionSpecial Encodings

The extreme exponent fields are reserved:

  • E=0E = 0, T=0T = 0 → signed zero ±0\pm 0.
  • E=0E = 0, T≠0T \ne 0 → subnormal (denormal): value (−1)S(0+T2−t)21−bias(-1)^S (0 + T 2^{-t}) 2^{1-\text{bias}}, with implicit leading 0, filling the gap around zero (gradual underflow).
  • E=2w−1E = 2^w - 1, T=0T = 0 → infinity ±∞\pm\infty.
  • E=2w−1E = 2^w - 1, T≠0T \ne 0 → NaN (Not a Number); quiet vs. signaling distinguished by the top fraction bit.
TheoremRounding Error Bound

Let fl(x)\mathrm{fl}(x) denote the correctly rounded value of a real xx in the normal range of FF. Then there exists δ\delta with

3
fl(x)=x(1+δ),∣δ∣≤u=12β1−p=2−p\quad \mathrm{fl}(x) = x(1 + \delta), \qquad |\delta| \le u = \tfrac{1}{2}\beta^{1-p} = 2^{-p}

where uu is the unit roundoff. Moreover, for any IEEE 754 basic operation op∈{+,−,×,÷, }\mathrm{op} \in \{+,-,\times,\div,\sqrt{\ }\},

4
fl(ab)=(ab)(1+δ),∣δ∣≤u\quad \mathrm{fl}(a \mathbin{\mathrm{op}} b) = (a \mathbin{\mathrm{op}} b)(1+\delta), \qquad |\delta| \le u

Derivation hint: round-to-nearest selects the closest grid point; the worst case is the midpoint, half a unit in the last place (ulp) away — divide that gap by the magnitude ≥βe\ge \beta^{e}.

Why It Holds / Derivation

ProofOf the relative error bound (3)

Step 1. Fix x≠0x \ne 0 in the normal range. Write ∣x∣=m⋅βe|x| = m \cdot \beta^{e} with m∈[1,β)m \in [1, \beta). The representable numbers in this binade are spaced exactly βe−(p−1)\beta^{e-(p-1)} apart; this spacing is one ulp.

Step 2. Round-to-nearest maps xx to the closest grid point, so the absolute error satisfies

∣fl(x)−x∣≤12 ulp=12βe−(p−1)=12βeβ1−p.|\mathrm{fl}(x) - x| \le \tfrac{1}{2}\,\text{ulp} = \tfrac{1}{2}\beta^{e-(p-1)} = \tfrac{1}{2}\beta^{e}\beta^{1-p}.

Step 3. Since the significand m≥1m \ge 1, we have ∣x∣=mβe≥βe|x| = m\beta^e \ge \beta^{e}. Divide:

∣fl(x)−x∣∣x∣≤12βeβ1−pβe=12β1−p=u.\frac{|\mathrm{fl}(x) - x|}{|x|} \le \frac{\tfrac{1}{2}\beta^{e}\beta^{1-p}}{\beta^{e}} = \tfrac{1}{2}\beta^{1-p} = u.

Step 4. Define δ=(fl(x)−x)/x\delta = (\mathrm{fl}(x)-x)/x; then ∣δ∣≤u|\delta| \le u and fl(x)=x(1+δ)\mathrm{fl}(x) = x(1+\delta). For β=2\beta = 2, u=2−pu = 2^{-p}.

Step 5. Equation (4) follows from the IEEE 754 mandate that each basic operation behave as if computed to infinite precision and then rounded once. Applying (3) to the exact result aba\mathbin{\mathrm{op}}b gives the bound. ■\blacksquare

∎
Figure
The uneven grid of floating point: spacing doubles at each power of two
Representable values (toy: p=3 bits) 1 2 4 8 gap = 0.25 gap = 0.5 gap = 1.0 Spacing (ulp) doubles each binade — relative gap stays ~constant.
WK
William Kahan
b. 1933

Often called "the Father of Floating Point," Kahan led the design of the Intel 8087 math coprocessor arithmetic that became the template for IEEE 754. A Berkeley numerical analyst, he championed correct rounding, gradual underflow (subnormals), and the principled handling of exceptions — features that vendors initially resisted as too costly. His compensated summation algorithm and tireless advocacy for reproducible arithmetic earned him the 1989 Turing Award. Kahan's enduring lesson: the hard part of floating point is not the average case but the adversarial corner cases that silently corrupt results.

Building Intuition

🧠 Intuition

Think of floating point as scientific notation with a fixed budget of significant figures. You always carry, say, 16 decimal digits — whether the number is 6.022×10236.022\times10^{23} or 1.602×10−191.602\times10^{-19}. The exponent is "free" range; the significand is where precision lives. So the number line is not a smooth continuum but a logarithmically-zoned ruler: fine ticks near zero, coarsening as you go out. Two consequences become obvious. First, adding a tiny number to a huge one can do nothing — the tiny one falls below the local tick spacing and rounds away. Second, subtracting two nearly-equal numbers wipes out leading digits, leaving noise (catastrophic cancellation). The constant-relative-error picture is the master key: it tells you errors compound multiplicatively, and that you should fear differences, not sums.

Worked Examples

ExampleEncoding 0.1 in binary64 — why it's inexact

Given: Decimal 0.10.1. Find its binary64 representation and the rounding error.

Step 1. In binary, 0.1=0.0001100110011…20.1 = 0.0001100110011\ldots_2, a repeating fraction (period "0011"). It is not a finite binary fraction, so it cannot be exact.

Step 2. Normalize: 0.1=1.100110011…2×2−40.1 = 1.100110011\ldots_2 \times 2^{-4}, so e=−4e = -4, biased E=−4+1023=1019=011111110112E = -4 + 1023 = 1019 = \texttt{01111111011}_2.

Step 3. The 52-bit fraction is the repeating pattern truncated and rounded-to-nearest:

T⋅2−52=0.1001100110011…(rounded).T \cdot 2^{-52} = 0.1001100110011\ldots(\text{rounded}).

The stored value is the nearest double:

fl(0.1)=0.1000000000000000055511151231257827021181583404541015625.\mathrm{fl}(0.1) = 0.1000000000000000055511151231257827021181583404541015625.

Step 4. The error is

fl(0.1)−0.1≈+5.55×10−18,∣δ∣0.1≈5.6×10−17<u=2−53≈1.1×10−16.\mathrm{fl}(0.1) - 0.1 \approx +5.55\times10^{-18}, \qquad \frac{|\delta|}{0.1}\approx 5.6\times10^{-17} < u = 2^{-53}\approx1.1\times10^{-16}.
fl(0.1)≈0.1+5.55×10−18,∣δ∣≤2−53\boxed{\mathrm{fl}(0.1) \approx 0.1 + 5.55\times10^{-18},\quad |\delta| \le 2^{-53}}

This is exactly why `0.1 + 0.2 != 0.3` in most languages.

ExampleCatastrophic cancellation in a quadratic root

Given: Solve x2−200000x+1=0x^2 - 200000x + 1 = 0 in binary64 using the textbook formula. Here a=1a=1, b=−200000b=-200000, c=1c=1.

Step 1. Discriminant: Δ=b2−4ac=4×1010−4=39999999996\Delta = b^2 - 4ac = 4\times10^{10} - 4 = 39999999996. Then Δ≈199999.99999000\sqrt\Delta \approx 199999.99999000.

Step 2. The "stable" root: x1=−b+Δ2=200000+199999.999992≈199999.999995x_1 = \dfrac{-b+\sqrt\Delta}{2} = \dfrac{200000 + 199999.99999}{2} \approx 199999.999995. Fine.

Step 3. The "naive" small root:

x2=−b−Δ2=200000−199999.999990002.x_2 = \frac{-b - \sqrt\Delta}{2} = \frac{200000 - 199999.99999000}{2}.

Here two ~2×1052\times10^5 numbers nearly cancel: about 11 leading digits agree and vanish, leaving only a few accurate digits.

Step 4. Stable alternative via x1x2=c/a=1x_1 x_2 = c/a = 1:

x2=ca x1=1199999.999995=5.0000000125×10−6.x_2 = \frac{c}{a\,x_1} = \frac{1}{199999.999995} = 5.0000000125\times10^{-6}.
x2≈5.0000000125×10−6 (via c/(ax1)), accurate to full precision\boxed{x_2 \approx 5.0000000125\times10^{-6}\ \text{(via } c/(a x_1)\text{), accurate to full precision}}

The subtraction form loses ~11 significant digits; the product form keeps all of them.

Common Misconceptions

⚠️ Common mistake

Floating point is not "approximate real arithmetic with random noise." It is deterministic and fully specified: every IEEE 754 operation produces a unique, correctly rounded result, identical across conforming hardware. The "errors" are not noise — they are exact, reproducible consequences of rounding. Two further traps:

  • Associativity fails: (a+b)+c≠a+(b+c)(a+b)+c \ne a+(b+c) in general, so compilers may not freely reorder sums, and parallel reductions can give different (still valid) answers.
  • Equality testing is dangerous: never write `if (x == 0.1)` after computing `x`; compare with a tolerance instead.
CounterexampleAddition is not associative

In binary64, let a=1016a = 10^{16}, b=1b = 1, c=−1016c = -10^{16}. Compute left-to-right: (a+b)+c(a + b) + c. Since 1<ulp(1016)=21 < \text{ulp}(10^{16}) = 2, the sum a+ba+b rounds back to 101610^{16}; then +c+c gives 0\boxed{0}. Compute right-grouped: a+(b+c)=1016+(1−1016)=1016+(−9999999999999999)=1a + (b + c) = 10^{16} + (1 - 10^{16}) = 10^{16} + (-9999999999999999) = \boxed{1}. Same three numbers, two different answers — associativity, an axiom of real arithmetic, simply does not hold.

Connections

connection

Floating point sits at the crossroads of pure and applied mathematics. The error bound (3) is the entry point to Numerical Stability and Conditioning, where the condition number measures sensitivity of a problem and backward error measures the quality of an algorithm. The base-β\beta positional encoding generalizes Positional Number Systems and connects to Binary Representation of Integers for the exponent and significand fields. Rounding analysis underpins Numerical Linear Algebra (e.g., the stability of Gaussian elimination) and Numerical Solution of ODEs. The logarithmic spacing of the grid is essentially a discretized Logarithm, which is why relative error, not absolute error, is the natural metric.

Real-World Applications

🔬 Where this appears

Historical Development

⏳ History
- 1914 — Leonardo Torres y Quevedo describes floating point in an electromechanical computing essay.
- 1941 — Konrad Zuse's Z3 uses a binary floating point format with exponent and significand — arguably the first working implementation.
- 1950s–1970s — Every vendor (IBM 360 hex floats, CDC, Cray, DEC) invents its own format; precision, rounding, and range all differ, making portable numerics nearly impossible.
- 1976 — Intel begins the 8087 coprocessor project; Kahan and students are hired to design its arithmetic.
- 1977–1985 — A fierce standards committee (the "KCS" draft by Kahan, Coonen, Stone) debates gradual underflow, NaNs, and directed rounding.
- 1985 — IEEE 754-1985 is ratified: formats, rounding modes, exceptions, and special values become law.
- 1987 — IEEE 854 generalizes to any radix (covering decimal).
- 2008 — IEEE 754-2008 merges 754/854, adds `binary16`, decimal formats, and the fused multiply-add (FMA).
- 2019 — IEEE 754-2019 refines recommended functions, augmented operations, and minimum/maximum semantics.

Subtleties & Limits

open-problem

Several deep difficulties remain practical headaches rather than solved theory:

  • The Table-Maker's Dilemma: correctly rounding transcendental functions (sin⁡\sin, exp⁡\exp, log⁡\log) requires knowing how many extra digits suffice to decide the rounding direction — and no general bound is known. Implementations use heuristics (Ziv's strategy), so correctly rounded libm functions are still not universal.
  • Reproducibility vs. performance: FMA, vectorization, and parallel reductions all change rounding; bit-reproducible parallel summation is an active research and engineering area.
  • Low-precision proliferation: `float8`, `bfloat16`, and posit/unum alternatives challenge IEEE 754's dominance; whether a successor standard should replace fixed-exponent floats with tapered precision is genuinely open.
  • Verified numerics: automatically proving tight error bounds for whole programs (not single operations) — interval and affine arithmetic help but remain conservative.

See Also

Numerical Stability and Conditioning · Binary Representation of Integers · Catastrophic Cancellation · Unit in the Last Place (ulp) · Kahan Summation Algorithm · Interval Arithmetic