由于进制的关系,十进制下的大多数小数,在二进制下无法完美的表示,只能表示为无限循环小数。

比如0.5可以表示为0.1,0.4则只能表示为0.011001100110......

十进制小数转换成二进制小数的方法,可以通过对小数部分乘2法来实现,

比如:0.4

0.4   *2    0.8

0.8   *2    1.6

0.6   *2    1.2

0.2   *2    0.4

取乘积的整数部分,得到,0.0110的无限循环。

还有一种方法就是把0.4看出2/5即2除以5,即10/101,通过除法运算也可以得到相同的值。

因此计算机有限的内存注定无法表示无限的循环小数,只能使用近似值代替。32位和64位的表示方法如下:

浮点数_二进制

其中阶码的值用移码表示,移码是符号位取反的补码,[X]移与[X]补的关系是符号位互为相反数(仅符号位不同)。

还需要注意的是,该阶码值需要减去偏移值127后才是正真的指数值,偏移值通常为2e-1 - 1,其中的e为阶码的长度。以单精度浮点数为例,它的指数域是8个比特,固定偏移值是28-1 - 1 = 128?1 = 127

在表示浮点数的时候,我们总是确保最高位是1,如果是0的话,则乘以2^n,即左移n位变成1。

因此23位的尾数可以表示24位有效数字。这种简化浮点数表示的操作称之为规格化。规格化后的数据都是如下格式

±1.xxxxxx*2^E

1.1010001*2^10100 表示成32位时,阶码需要加上127

 0001 0100

+0111 1111

——————

 1001 0011

因此,当浮点数是正数的时候,最小值的编码如下:

浮点数_二进制_02

阶码为0-127=127,小数部分为1,因此该值表示 2^-127

浮点数_十进制_03

阶码为255-127=128,小数部分为1.11111111111111111111111(正数部分为1,小数部分23个1),因此该值表示 (2-2^-23)*2^128

1.11111111111111111111111=2-2^-23,这个等式让我一开始也愣了下,想了下有多种方式证明。

1.11111111111111111111111=2^0+2^-1+2^-2+2^-3+2^-4………………+2^-22+2^-23

等比数列求和公式    
浮点数_二进制_04

a1=1,q=1/2, n=24

因此最终的结果等于2-2^-23

   

还有一种计算方式

1.11111111111111111111111=10-0.000000000000000000000001

二进制表示即为2-2^-23

同理,最高位如果改成1的话,表示负数。因此浮点数的取值范围为:

[- (2-2^-23)*2^128,-2^-127] 和 [2^-127, (2-2^-23)*2^128] 换算成十进制则为  
浮点数_二进制_05

如该数轴的显示,其他区域将会导致溢出。实际上,这个浮点数在数轴上并不是连续的,只能是一个十分接近的近似值,但这个近似值已足够满足一般的应用了。

上述浮点数的表示只是一种通常的解释方式,实际使用中有会有部分改进,比如上述的浮点数没法表示真正的0。

目前使用最广泛的浮点数的表示方法是IEEE 754标准所定义的,该标准定义了32位单精度和64位双精度。

IEEE754标准定义了一些特殊值。如下图所示,摘自维基百科

浮点数_十进制_06

逐行解释:

1.正零和负零,除去符号位,所有的数都为0的情况,认为是±0。这个0是一个精确值。

2.当指数是0111 1111=127时,减去偏移量127,即实际指数为0,尾数全零,默认的小数点前的数字是1,所以这种情况认为是±1.0

3.当指数域为0,尾数位非0时,认为是非规格化的数。规格化的数字,默认认为小数点前是1,而非规格化的数字,默认认为小数点前的数字是0。

  并且,当数字是非规格化时,规定偏移量比原先大1,变成了-126。

4.指数域不为0,为规格化的数字,此时尾数域默认小数点前的数字是1,最小的规格化的数字的实际指数为1-127=-126,即最小的规格化数字为±2^-126

5.指数最大不能为255,255为保留值,只能是254,因此,实际指数值为254-127=127。最大的规格化的数字即1.11111111111111111111111(二进制)^127

6.指数域全1,尾数域全0,表示正负无穷。

7.指数域全1,尾数域不为0,是非法的浮点数。

以上规则,总结如下:

形式指数小数部分
00
非规约形式0非0
规约形式1-254任意
无穷2550
NaN255非零

引入非规约形式的浮点数是很有必要的有效可以使用的,只是它们的绝对值已经小于所有的规约浮点数的绝对值;即所有的非规约浮点数比规约浮点数更接近0。

浮点数_十进制_07

它填补了一部分空隙,使得数字更均匀覆盖数轴,非规格化数字的使用,称之为逐级下溢,如果不采用这种方式,那么绝对值最小的规约浮点数与0的距离是相邻的小浮点数之间距离的2^23倍!可以说是非常突然的下溢出到0。这种情况的一种糟糕后果是:两个不等的小浮点数X与Y相减,结果将是0.

根据之前列出的IEEE754中的一些特殊值,可以看出,32位浮点数值的取值范围-3.4 × 10^38 到 +3.4 × 10^38

参考资料

《计算机组成与体系结构》

https://zh.wikipedia.org/wiki/IEEE_754