一直以来都不能非常清楚地记住浮点数的表示方式,这段时间开始重读 CSAPP 的第二章中浮点数表示的部分,大致上弄清楚了 IEEE 浮点数的表示方式。
简单介绍一下 IEEE 浮点数的表示方式,细节部分可以参考 CSAPP 和 维基
二进制小数表示
首先理解一下十进制小数的表示方式,我们以下面这种方式表示十进制小数:
dndn−1...d1d0.d−1...dm
表示的值为:
i=m∑n10idi
类似地,二进制小数的表示方式:
bnbn−1...b1b0.b−1...bm
i=m∑n2ibi
例如二进制小数
11.012=1×21+1×20+0×2−1+1×2−2=2+1+0+0.25=3.25
现在考虑如何对这种二进制小数进行编码,一种可行的方式是定点小数。即将小数点的位置固定。例如使用 16 位二进制数来编码定点小数。可以做如下规定:
- 第 15 位为符号位。
- 第 14 ~ 9 位表示小数点前的数
- 第 8 ~ 0 位表示小数点后的数
那么,11.01 可以编码为 0000011010000000。
这种表示方式的优点是比较简单,但是能够表示的小数的范围就十分的小。不考虑小数点后的数字,这种方式能够表示的整数范围就只能是 −26+1∼26−1。
于是,考虑到不去固定小数点的位置。而是根据当前的数字来确定小数点的具体位置。这样,就有了一种新的表示小数的方式,即浮点数。以下面这种方式表示(不考虑编码方式):
V=(−1)s×M×2E
其中,s 表示符号位,E 表示阶码,M 表示尾数。
通过这种方式,就有了 IEEE 754 浮点数规范。其具体定义了浮点数的位级编码规则。
IEEE 浮点数表示
首先, IEEE 将浮点数编码为 32 位或者 64 位。其中,32 位的规则如下:
- 第 32 位表示符号
- 第 31 ~ 23 位表示的值为 E,其位级表示记为 exp
- 第 22 ~ 0 位表示的值 M, 其位级表示记为 frac
64 位编码表示中,exp 长度为 11,frac 长度为 52。与 32 位类似。
根据 exp 和 frac 的表示的不同,IEEE 浮点数规范将浮点数分为 4 类:
- 规格化数: exp 不为全 0 和全 1
- 非规格化数: exp 为全 0
- 无穷大: exp 为全 1 且 frac 为全 0
- NAN: exp 为全 1 且 frac 不为全 0
规格化数
首先 E=e−Bias, 其中 e 为 exp 所表示的无符号数。Bias 的值为 2k−1−1,k 为 frac 部分的长度。例如,32 位编码时 k 的值为 8,于是 Bias 的值为 127,最终, E 的范围为 −126∼127。
其次 M=1+f,其中 f 为 0.fnfn−1...f0 所表示的值。这里,通过将 f 加 1 获得了一个额外的表示精度位。
非规格化数
其 E=1−Bias,而 M=f。
根据该定义,当 frac 为全 0 时, M=0。于是:
V=(−1)s×E×0=0
根据 s 的值的不同,得到了表示 0 的两种方式,记为 +0 和 −0。
无穷大
根据符号位分为 +∞ 和 −∞。
总结
一般来说,非规格化数用于表示 0 和非常接近 0 的数。而相对其他能正常表示的数则用规格化数表示,溢出的值则用无穷大表示。当溢出的小数部分为非 0 即可用 NAN(Not A Number)表示。当一些运算的结果不是实数或者无穷时,就会返回 NAN,比如 −1。
写在最后
写技术文章需要严谨、正确,可能我比没有做到。所有如果有疑惑的话,可以学习一下 CSAPP 中和此有关的内容。
文章标题:IEEE 浮点数表示
文章链接: https://blog.guanglai.me/posts/ieee-floating-point-representation/
商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接。您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但分发衍生作品时必须采用相同的许可协议。
本文采用 CC BY-NC-SA 4.0 进行许可。