03 · 浮点表示、舍入与运算
来源:第 3 讲 pp.3~48;小班第 3 讲;教材 §2.4;2022、2023、2024 期中第二大题以及 2025 阶段卷第 4~6 题。
二进制小数与定点#
1011.101₂ = 8+2+1+1/2+1/8 = 11.625。有限二进制小数的最简分母只能含因子 2,所以 1/10 不能精确有限表示;1/8 可以。定点预先固定小数点位置,硬件和舍入容易控制、等间距,但固定总位数下动态范围有限。浮点通过指数移动小数点,范围大但间距不均匀。
通用 IEEE 风格公式#
设符号位 s,阶码字段 e 共 k 位,小数字段 f 共 n 位,Bias=2^(k-1)-1,p=n+1 为规格化有效位精度。字段 f 是整数;公式中的 f/2^n 才是二进制小数。
| 类别 | 阶码条件 | M | E | 数值 |
|---|---|---|---|---|
| 规格化 | 0 < e < 2ᵏ-1 | 1+f/2ⁿ | e-Bias | (-1)ˢ·M·2ᴱ |
| 非规格化 | e=0 且 f≠0 | f/2ⁿ | 1-Bias | (-1)ˢ·M·2ᴱ |
| 有符号零 | e=0 且 f=0 | 0 | 1-Bias | +0 或 -0 |
| 无穷 | e=2ᵏ-1 且 f=0 | — | — | +∞ 或 -∞ |
| NaN | e=2ᵏ-1 且 f≠0 | — | — | 非数 |
非规格化数没有隐含的 1,但指数用 1-Bias,不是 -Bias。这让最大非规格化数与最小正规格化数之间恰好仍差一个最小非规格化单位,实现渐进下溢。
| 格式 | s/k/n | 精度 p | Bias | 最小正非规格化 | 最小正规格化 | 最大有限值 |
|---|---|---|---|---|---|---|
| binary32 | 1/8/23 | 24 | 127 | 2⁻¹⁴⁹ | 2⁻¹²⁶ | (2-2⁻²³)·2¹²⁷ |
| binary64 | 1/11/52 | 53 | 1023 | 2⁻¹⁰⁷⁴ | 2⁻¹⁰²² | (2-2⁻⁵²)·2¹⁰²³ |
单精度最大约 3.40×10³⁸,最小正规格化约 1.18×10⁻³⁸,有效十进制数字约 7 位;双精度最大约 1.80×10³⁰⁸,最小正规格化约 2.23×10⁻³⁰⁸,有效数字约 16 位。有效数字是精度概念,不是小数点后固定的位数。
范围、间距与计数#
最小正非规格化 = 2^(1-Bias-n)
最大正非规格化 = (1-2^-n)·2^(1-Bias)
最小正规格化 = 2^(1-Bias)
最大正有限值 = (2-2^-n)·2^((2^k-2)-Bias)
规格化 binade [2^E,2^(E+1)) 内相邻数间距为 2^(E-n);非规格化区域等间距。越接近大数,绝对精度越粗。1 后面的间距是 2⁻ⁿ,最近偶数舍入的常见相对误差界为 2⁻ᵖ(规格化且无溢出等条件下)。1 前面的间距比 1 后面小一半,不能跨边界机械套同一个 ULP。
精度 p 的格式能连续精确表示从 -2ᵖ 到 2ᵖ 的整数(还需指数范围足够),不意味着 2ᵖ 是可精确表示的最大整数。更大的 2 的幂仍可精确表示。
固定符号时 NaN 编码数为 2^n-1,两种符号共 2(2^n-1)。有限位模式数是 2(2^k-1)2^n;若把 +0/-0 视为同一个实数,互异有限实数个数再减 1。增加阶码位、减少小数位,会改变范围、精度和特殊编码数,不仅仅是“同样多的实数换个分布”。
“最大负非规格化”按数值顺序是最接近 0 的负数;“最小负非规格化”是绝对值最大的负非规格化数。必须区别于“最大绝对值”。
编码与解码:完整步骤#
编码 -13.25:绝对值为 1101.01₂=1.10101₂×2³;s=1,e=3+127=130=10000010₂,f=1010100...0(补到 23 位)。最终 binary32 为 0xC1540000。小端内存字节是 00 00 54 C1。
解码 0x40400000:s=0,e=128,f/2²³=0.5,所以 M=1.5、E=1,值为 3。解码时先分字段和分类,再决定隐藏位;不要一律补 1。
自定义 1/3/4 格式:Bias=3,0xBD 的 s=1、e=3、f=13,因此值为 -(1+13/16)·2^0=-1.8125;9/64 是非规格化,单位是 2⁻⁶,f=9,编码 0x09。题目给实数 1 的编码可反推 Bias、指数宽度和小数宽度。
最近偶数舍入#
先比较被丢弃部分与半个间隔;小于半间隔舍去,大于则进位;恰好一半时,选保留后最低位为 0 的结果。“向偶数”不是总舍入到偶数整数。
保留三位二进制小数:
| 原数 | 保留部分 | 舍弃部分 | 结果 |
|---|---|---|---|
| 101.100011 | 101.100 | 011,小于一半 | 101.100 |
| 101.100101 | 101.100 | 101,大于一半 | 101.101 |
| 101.100100 | 101.100 | 100,恰好一半,最低位 0 | 101.100 |
| 101.111100 | 101.111 | 100,恰好一半,最低位 1 | 110.000 |
工程判定:guard 为第一舍弃位,sticky 为其后各位的或,lsb 为最后保留位;最近偶数的进位条件是 guard && (sticky || lsb)。进位可能导致有效数溢出,必须重新规格化。
其他模式:向零、向 +∞、向 -∞。对负数,“向下”是更负而不是靠近 0。默认近偶数减少反复遇到中点时持续单向偏差,但不能说任意数据集都无偏。
加法、乘法与异常#
加法:比较指数 → 小指数有效数右移对阶并保留舍入信息 → 带符号相加/相减 → 规格化 → 舍入 → 检查上溢、下溢、零。相近数相减可能发生严重消去,使已有的相对误差变大。
乘法:符号异或 → 指数相加 → 有效数相乘 → 规格化 → 舍入 → 范围检查。不要把指数字段直接相加后忘记减 Bias;字段编码不是实际 E。
IEEE 默认模式下超出有限范围可能得到无穷,下溢可能得到非规格化或零。浮点状态还包括无效、除零、上溢、下溢、不精确等异常标志;它们不同于程序必须立即抛出异常或终止。
零、无穷与 NaN#
+0 与 -0 比较相等,但符号可由 signbit 或某些运算体现;IEEE 非陷阱语义下 1/+0=+∞、1/-0=-∞。∞-∞、0×∞、0/0 会得到 NaN。NaN 与任何数(包括自己)的 == < <= > >= 都是假,!= 为真。
NaN 有多个有效载荷编码,可区分 quiet/signaling NaN,并携带诊断信息;具体传播与载荷保留规则依实现,不能把 payload 当通用稳定错误码。符号位也存在,但 NaN 不形成普通的数值正负顺序。
对非负有限数,IEEE 位串按无符号比较与数值顺序一致;负数顺序反向,有符号零与 NaN 又需要特殊处理,所以不能对所有 float 直接按 int 比较。
代数性质与 C 转换#
浮点加法和乘法通常可交换,但结合律、分配律不普遍成立;NaN、无穷、有符号零还会影响等式和特殊情形。在固定舍入模式、排除 NaN 的普通数值排序中,正确舍入加法保持弱单调性;精度损失会破坏严格单调性(可能相等),不能把它误说成一定反转大小。乘以非负常数才保持方向,负数会反向,0×∞ 会产生 NaN。
- 32 位 int → double 精确,因为 53 位有效精度足够。
- int → float 可能舍入,32 位 int 的范围不致使 binary32 溢出。
- float → double 对有限值精确;double → float 可能舍入、上溢和下溢。
- 浮点 → 整数向零截断;NaN、无穷或截断后超出目标范围,不能依赖可移植 C 给某个固定整数。
(float)(double)x == (float)x对 32 位 int x 成立;整数先精确进入 double。- 三个 32 位整数转 double 后相加,中间精确和仍远小于 53 位精度极限,所以该特定域内加法结合律成立;这不证明任意 double 的结合律成立。
- 三个整数转 double 后相乘可能超过精度,结合律不保证成立;
dx/dx == dz/dz在某个原整数为零时可能失败。
例:binary32 中 (16777216.0f+1.0f)-16777216.0f 为 0,因为 2²⁴ 之后间距为 2,加 1 恰在中点,舍到偶数有效数。真实数学结果为 1。
FP8 与低精度格式:按题设定义#
2023 期中使用 E5M2 与一种 E4M3:E5M2 可按 1/5/2 的 IEEE 风格计算,Bias=15,最大有限值 57344;题设 E4M3 保留指数、小数全 1 为 NaN、其余扩展有限范围,最大值为 448。不能把该 E4M3 的全 1 指数一律判成无穷。
FP16(1/5/10)、BF16(1/8/7)展示范围和精度的权衡;BF16 指数范围接近 FP32,精度较低。训练/推理中可使用混合精度和高精度累加,但不能从存储格式推定累加也用相同格式。这里解释格式原理,不以某一年的硬件支持列表代替考题约定。
自检#
任选 k、n,能推导四个边界、相邻间距、NaN 数量和两种零;能把十六进制编码和内存字节分开;能处理跨规格化边界的舍入;能用输入范围证明某个表达式成立,而不是只背“浮点不满足结合律”。教材作业 2.86、2.87、2.89。