浮点数的那些事
待补,含部分AI
浮点数是遵循 IEEE 754 的标准规定存储的,浮点数主要是由符号位,指数位和尾数这三部分组成的,而且有一些特殊的规定,其中包含 NaN 这个恶心人的玩意。
浮点数主要也就是32位单精度和64位双精度这两种:
| 特性 | 单精度 (float) | 双精度 (double) |
|---|---|---|
| 总位数 | 32 位 | 64 位 |
| 符号位 | 1 位 | 1 位 |
| 指数位 | 8 位 | 11 位 |
| 尾数位 | 23 位 | 52 位 |
| 指数偏移量 (Bias) | 127 | 1023 |
| 有效精度 | 约 7 位十进制数 | 约 16 位十进制数 |
浮点数本身是通过类似科学计数法的办法进行存储的,即:
其中的 \(m\) 就是指数位的数值,而尾数就是 \(1.xxx\),\(s\) 就是符号位。
通过这种方式可以保证数组的大小和部分精度,但是因为尾数的原因,精度丢失是几乎必定的,所以一般浮点数对比都是看数值差距有多少,如只要 abs(n - m) < 1e-6 就基本上可以认为 \(n\) 和 \(m\) 数值相同。
# 浮点数的底层原理和精度损失问题 这篇文章有很多额外信息,剩下的就看看这个把。
特殊的规定
浮点数也有些特殊的规定,基本上都是围绕着指数位来规定的。
下面是 AI 写的,不过可以看看。
1. 指数采用“移码”,但有特例(全0和全1被征用)
- 单精度偏置127,双精度1023。但指数位全0和全1不参与常规移码运算,它们被强行征用做特殊标志。
2. 规定“非规格化数”(Denormalized Numbers)—— 让下溢更平滑
-
普通情况:尾数隐含前导
1(即 1.xxx1.xxx)。 -
特殊规定(指数全0时):隐含前导
1强制变成0(即 0.xxx0.xxx),且指数固定为-126(单精度)或-1022(双精度)。 -
作用:允许表示比最小规格化数还小的数(渐进下溢),防止两个极小数相减直接变成0。代价:处理非规格化数的运算极慢(可能慢数十倍)。
为什么会出现隐含前导 \(0\) 呢?是因为指数位已经低到最低了,没法继续再低了,因此卡死了,所以出现了前导 \(0\)。
这种限制导致了非规格化数有一个极端的边界:
-
最小规格化数:\(1.000×2^{−126}\)
-
最大非规格化数:\(0.111×2^{−126}\)
-
最小非规格化数:\(0.001×2^{−126}\)
3. 规定“正零”和“负零”(±0)
-
符号位可以是0也可以是1,指数和尾数全为0。
-
+0和-0在数值比较中相等,但在某些数学函数(如1/-0会得到-Inf)中有不同表现。
4. 规定“无穷大”(Inf)和“非数字”(NaN)
-
无穷大:指数位全1,尾数全0。符号位区分正负。
-
NaN(Not a Number):指数位全1,尾数不为0(只要不为0就是NaN)。
- 还细分 静默NaN(sNaN) 和 信号NaN(qNaN),前者安静传递,后者会触发浮点异常信号。
5. 规定“舍入模式”(默认向偶数舍入)
-
不采用截断。默认是 “就近舍入,平局向偶数”(Round to Nearest, Ties to Even)。
-
特殊规定:如果真实结果正好卡在两个可表示数的正中间,看目标最低有效位,选偶数的那个。这是为了保证舍入误差在统计上不偏向正无穷或负无穷。

浙公网安备 33010602011771号