TL;DR: E4M3 trades range for precision: it tops out at 448 with a 2^-3 mantissa step, while E5M2 reaches 57,344 with a 2^-2 step, so E4M3 rounds about twice as finely. Inference uses E4M3 with a scale for weights, activations and usually the KV cache, because a scale fixes the range problem and nothing fixes lost mantissa bits. E5M2 is the format for tensors whose range you cannot scale ahead of time, which in practice means training gradients.
How to approach it
Derive the numbers from the bit layout rather than reciting them, because the follow-ups ask why 448 and not 480. Then separate two properties that candidates blur: dynamic range (how many binades fit) and precision (how fine the grid is within a binade). Ask whether the deployment applies scales, since that decides the format, and which hardware it targets, because AMD's MI300 family uses a different FP8 dialect.
A strong answer
Both formats are 1 sign bit plus exponent and mantissa. The OCP E4M3 variant (called e4m3fn in PyTorch) has no infinities and gives up only one bit pattern to NaN, which is why its top exponent still holds finite values:
E4M3: 4 exponent bits, bias 7, 3 mantissa bits
max = 2^(15 - 7) x 1.75 = 256 x 1.75 = 448 (S.1111.111 is NaN)
min normal = 2^(1 - 7) = 2^-6 = 0.0156
min subnorm= 2^-6 x 2^-3 = 2^-9 = 0.00195
step in [1, 2) = 2^-3 = 0.125, worst rounding error 6.25%
E5M2: 5 exponent bits, bias 15, 2 mantissa bits, IEEE-style inf and NaN
max = 2^(30 - 15) x 1.75 = 32,768 x 1.75 = 57,344
min normal = 2^(1 - 15) = 2^-14 = 6.1e-5
min subnorm= 2^-14 x 2^-2 = 2^-16 = 1.5e-5
step in [1, 2) = 2^-2 = 0.25, worst rounding error 12.5%
range in binades: E4M3 log2(448 / 2^-9) = 17.8 E5M2 log2(57,344 / 2^-16) = 31.8
| Property | E4M3 (OCP) | E5M2 | BF16 for scale |
|---|---|---|---|
| Largest finite | 448 | 57,344 | about 3.4e38 |
| Mantissa bits | 3 | 2 | 7 |
| Infinity | none | yes | yes |
| Typical inference use | weights, activations, KV | unscaled KV, rarely | the reference |
The decision rests on one observation: range is cheap to buy back and precision is not. A per-tensor, per-channel or per-block scale maps a tensor's maximum onto 448, so E4M3's narrow window is placed wherever the data lives. Nothing restores a lost mantissa bit. Rounding a tensor of Gaussian values with one large outlier, scaled so its maximum hits each format's top, gives an RMS relative error of 1.9% in E4M3 and 3.6% in E5M2 (a synthetic illustration from a PyTorch cast, not a model measurement). One mantissa bit is a factor of two in error, as the step sizes predict.
So in inference:
- Weights are E4M3 with per-channel or per-block scales computed offline. Their range is known exactly.
- Activations are E4M3 with scales computed per tensor (static, from calibration) or per token or per block (dynamic, at runtime). DeepSeek V3 reports E4M3 on all tensors in training, with fine-grained block scales, which shows how far scaling stretches the narrow format.
- The KV cache is E4M3 with a scale when the engine supports one. vLLM's
kv_cache_dtypeaccepts bothfp8_e4m3andfp8_e5m2on CUDA (v0.31.0, checked October 2026); E5M2 exists for the case where no scale is calibrated and the cast has to survive whatever magnitudes appear. - Gradients in FP8 training are where E5M2 earns its place: their range swings across steps and layers, and a scale lags behind.
The reversal condition is the scale. If a tensor must be cast with no scale, or with a stale one, E4M3 overflows at 448 and E5M2's 31.8 binades are the safer choice. Once a fresh scale exists, E4M3 wins.
One portability trap belongs in any senior answer. AMD's MI300X (gfx942) implements the FNUZ variants: no negative zero, NaN encoded as the bit pattern for negative zero, and an exponent bias one higher. E4M3 FNUZ tops out at 240 instead of 448, and reading a byte in the wrong dialect returns a value off by exactly 2x. A checkpoint quantized for H100 needs conversion, with its scales adjusted, before it runs there.
What interviewers probe next
"What happens when a value above 448 is cast to E4M3?" There is no infinity, so the result is NaN or a saturated 448 depending on the conversion routine, and kernels clamp to the maximum explicitly before casting so an overflow never turns into NaN.
"Why is E4M3's maximum 448 and not 480?" The all-ones pattern S.1111.111 is reserved for NaN, so the top exponent holds mantissas up to 1.110 binary, which is 1.75 x 256.
"Does FP8 accumulate in FP8?" No. Tensor cores multiply FP8 inputs and accumulate at higher precision, and a kernel promotes partial sums to FP32 to keep long reductions accurate.
How it's scored
Weak: says E5M2 is "more accurate because it has more range", or quotes 448 and 57,344 without being able to derive either.
Hire: derives both maxima from exponent bias and mantissa width, states that E4M3 has twice the resolution, and assigns E4M3 to weights and activations with scales.
Strong Hire: argues that scaling recovers range but nothing recovers precision, names the unscaled-KV and gradient cases where E5M2 wins, handles overflow on cast, and flags the FNUZ dialect on MI300X with its 240 maximum.
Common mistakes
- Treating E5M2 as the "safe" default for weights, which doubles rounding error for no benefit when the weight range is known offline.
- Computing E4M3's maximum as 480 by assuming IEEE-style handling of the top exponent.
- Forgetting the scale is part of the format in practice: an FP8 tensor without its scale cannot be dequantized.
- Loading OCP FP8 bytes on MI300X as if they were FNUZ, which halves or doubles every value with no error raised.