计算机是如何表示浮点数的

相对于整数的表示,计算机对浮点数的表示稍显麻烦,理解计算机是如何表示浮点数的对于编写程序,尤其是对数据精度要求极高的程序十分有帮助。

20世纪80年代的时候各个计算机生成厂家都在努力的制定自己的浮点数表示规则,因此当时的浮点数表示并不统一,有的关注精度,有的关注表示的范围,还有的更关注执行的速度和简便性。直到1985年IEEE标准757的推出,这种情况才得以改变。

我们知道,十进制数dmdm-1··· d1d0 . d-1d-2···d-n的表示方法为每个十进制位di 乘以其对应位的权重然后再将其相加得到:

怎样表示浮点数(计算机是如何表示浮点数的)(1)

小数点左边i=0时d0的权重为100=1,每向左看一位那么相应权重需要乘以10,而小数点右边每向右看一位相应位置权重要除以10. 因此 d-1的权重为10-1而d-n的权重为10-n。所以小数点左边的权重是10的非负幂得到十进制小数的整数部分,而小数点右边的权重是10的负幂得到小数部分。

二进制浮点数bmbm-1··· b1b0 . b-1b-2···b-n我套用十进制浮点数的表示方法,只是权重不再乘以10的幂而是要用2的幂代替。

怎样表示浮点数(计算机是如何表示浮点数的)(2)

和十进制同样的分析,小数点左边i=0时b0的权重为20=1,每向左看一位那么相应权重需要乘以2,而小数点右边每向右看一位相应位置权重要除以2. 因此 b-1的权重为2-1而b-n的权重为2-n。所以小数点左边的权重是2的非负幂得到二进制小数的整数部分,而小数点右边的权重是2的负幂得到小数部分。

上面的表示方法称为定点法。看似不错,但是考虑计算机表示数据的位数有限,一般float类型的单精度数用4个字节(32个bit)来表示,而double型双精度数用8个字节(64个bit)来表示。因此在上面的表示方法中精度十分有限。比如:十进制表示法无法准确表示1/3, 5/7这样的数字。而二进制表示法只能表示那些可以写成 的数。其它值只能近似表示,而且无法有效的表示范围很大的浮点数。

IEEE中规定的浮点数表示方法有效解决了这个问题,下面给出其具体表示法:

IEEE中规定的浮点数表示方法用

怎样表示浮点数(计算机是如何表示浮点数的)(3)

来表示一个浮点数。下面具体说明:

  1. 上式中 (-1)s决定该浮点数的符号, s=1,该浮点数为负,s=0,该浮点数为正。
  2. M表示尾数(significand),二进制小数,它的范围是[1, 2), 或者[0, 1)。注意由于精度问题,前面采用数学上的的左闭右开区间表示并不准确。这里定义一个误差量ɛ。那么M的范围可以表示为1 ~ 2-ɛ 或者 0 ~ 1-ɛ。实际上从M的英文表达更容易理解它的含义。
  3. E表示阶码(exponent),很明显E是用来计算权重的。E可以是负数,权重的值为2E 。E的英文表达清楚的表明了其含义。

由于阶码E和尾数M的值需要进行处理才能得到,因此这里将M和E分别看做m和e的函数。至此浮点数的三部分可以分为s, e, 和 m 三部分。因为符号位只有两个状态0和1,因此用1位表示即可。对于m和e则需要用多个bit来表示。

对于单精度浮点数,e用8位表示,而m用23位表示。这样 符号位数 e占用位数 m占用位数 = 1 8 23 = 32 位。在实际内存中符号位占据最高位(第31位),接下来8位(30 ~ 23位)用来表示e,剩下的23位(22 ~ 0位)用来表示m。参见下图。

而对于双精度浮点数来说,e用11位表示,m用52位表示。这样 符号位数 e占用位数 m占用位数= 1 11 52 = 64 位。在实际内存中符号位占据最高位(第63位),接下来11位(62 ~ 52位)用来表示e,剩下的52位(51 ~ 0位)用来表示m。参见下图。

怎样表示浮点数(计算机是如何表示浮点数的)(4)

浮点数在内存中的表示

由于单精度和双精度在讨论中类似,下面针对单精度浮点数进行讨论。

由于e的值由8个bit表示, e的值计算机会按照无符号数解释,所以其表示的范围为[0, 255]。根据e的值,被编码的值可以分为三种情况:

  1. e的值大于0 并且 小于255,这种数我们成为规范化的数。
  2. e的值等于0,这种数我们称为非规范化的数。
  3. e的值等于255,这里又分为两种情况,第一种情况是尾数m=0,此时表示该数为无穷大。第二种情况是尾数m≠0,此时表示NaN(Not a Number)不是一个数。

上面三种情况(第3种情况又分为两个子情况)可以参考下图。可以看出阶码E决定一个数是规格化的,非规格化的还是特殊值。

怎样表示浮点数(计算机是如何表示浮点数的)(5)

浮点数的三种情况

下面对每种情况进行分析:

  1. 规格化的值

在这种情况下,e 的值 大于 0 并且小于255,这时阶码E会被计算机解释为以偏置Biased形式表示的有符号数。因此阶码E=e-Bias, 这里Bias为2(k-1) – 1(对于单精度k=8, 对于双精度k=11), 由于这里以单精度为例讨论,因此Bias = 27-1 = 127。根据E=e-Bias, 可得出阶码E的取值范围为-126 ~ 127。

关于m部分,计算机会将其解释为小数值。0.xxxxx, 因此 0 ≤ m < 1。计算机会将尾数M进行这样的: M=1 m。因此M可以看做二进制小数 1.bnbn-1··· b1b0 的数字。

  1. 非规格化的值

当e = 0 时,所表示的数即为非规格化的数。这种情况下E = 1- Bias,而尾数M=m。

为什么要有非规格化的数呢?(1),非规格化的数提供了一种表示0的方法,在规格化数中,尾数M总是大于等于1的,因此无法表示0。由于符号位的存在,因此浮点数表示中存在 0.0和-0.0。(2),非规格化的数可以表示那些非常接近于0.0的数,它们可以逐渐溢出(gradual underflow), 使其数值分布均匀地接近于0.0。

  1. 特殊值

当e = 255 时, 如果m= 0,则表示无穷大。S=0时表示 ∞,s=1时表示-∞。如果m ≠ 0, 则表示NaN。比如在进行除0时得到的结果就可以用NaN表示。它还可以在某些应用中表示未初始化的数据。

以上就是浮点数是如何在计算机中表示的,这里再举一个例子说明一下:

比如这里 有个32bits的二进制数00101010000111000100000000000000,那么它表示的浮点数是多少呢?根据前面的知识我们来进行下面的分析,32bits表示的是一个单精度的浮点数, 因此进行s, e, m三部分划分。下图展示了计算全部过程:

怎样表示浮点数(计算机是如何表示浮点数的)(6)

计算过程

Reference:Computer Systems: A programmer’s Perspective

,