#428 · Deep Learning · Hard
⊣ Solve on deep-ml.comCompare the precision characteristics of different number formats used in deep learning: FP16, BF16, FP8 (E4M3 and E5M2), and FP4 (E2M1). For each format, compute the maximum representable value, minimum positive normal value, machine epsilon, and the number of representable values.
def number_format_comparison() -> list[dict]:
formats = []
def compute_props(name: str, sign_bits: int, exp_bits: int, man_bits: int, exp_bias: int = None) -> dict:
if exp_bias is None:
exp_bias = (1 << (exp_bits - 1)) - 1
max_exp = (1 << exp_bits) - 2 - exp_bias # all-1s exponent reserved
# Max value: (2 - 2^(-man_bits)) * 2^max_exp
max_val = (2.0 - 2.0 ** (-man_bits)) * (2.0 ** max_exp)
# Min positive normal: 1.0 * 2^(1 - bias)
min_normal = 2.0 ** (1 - exp_bias)
# Machine epsilon: 2^(-man_bits)
epsilon = 2.0 ** (-man_bits)
# Min positive subnormal: 2^(1-bias) * 2^(-man_bits)
min_subnormal = min_normal * (2.0 ** (-man_bits))
# Number of representable values (including +/- zero, normals, subnormals, not counting inf/nan)
num_normals = 2 * ((1 << exp_bits) - 2) * (1 << man_bits) # sign * exponents * mantissas
num_subnormals = 2 * ((1 << man_bits) - 1) # sign * (mantissa != 0)
total_values = num_normals + num_subnormals + 2 # +0, -0
return {
"name": name,
"total_bits": sign_bits + exp_bits + man_bits,
"sign_bits": sign_bits,
"exponent_bits": exp_bits,
"mantissa_bits": man_bits,
"exp_bias": exp_bias,
"max_value": round(max_val, 6),
"min_normal": min_normal,
"min_subnormal": min_subnormal,
"epsilon": epsilon,
"num_representable": total_values
}
formats.append(compute_props("FP16", 1, 5, 10)) # IEEE 754 half
formats.append(compute_props("BF16", 1, 8, 7)) # Brain float
formats.append(compute_props("FP8_E4M3", 1, 4, 3)) # FP8 E4M3
formats.append(compute_props("FP8_E5M2", 1, 5, 2)) # FP8 E5M2
formats.append(compute_props("FP4_E2M1", 1, 2, 1)) # FP4 E2M1
return formats