文档介绍:标题: 解读IEEE原则754:浮点数表达                                                           
                       
       
格化形式。此时e,m的计算都非常简朴。
  
注意,此时小数点左侧的隐含位为0。   为什么e会等于(1-bias)而不是(-bias),这重要是为规格化数值、非规格化数值之间的平滑过渡设计的。后文我们还会继续讨论。
有了非规格化形式,我们就可以表达0了。把符号位S值1,其他所有位均置0后,我们得到了 -; 同理,把所有位均置0,则得到 +。非规格化数尚有其她用途,例如表达非常接近0的小数,并且这些小数均匀地接近0,称为“逐渐下溢(gradually underflow)”属性。
3、特殊数值: 当E的二进制位全为1时为特殊数值。此时,若M的二进制位全为0,则n表达无穷大,若S为1则为负无穷大,若S为0则为正无穷大; 若M的二进制位不全为0时,表达NaN(Not a Number),表达这不是一种合法实数或无穷,或者该数未经初始化。
五、范例
仔细研读第四点后,再回忆一下文章开头计算n的公式,你应当写出一种浮点编码的实际值n了吧? 还不能吗?不急,我先给你示范一下。我们假定N是一种8位浮点数,其中,S占1位,E占4位,M占3位。下面这张表罗列了N也许的正数形式,也涉及了e、m等值,请你对照着这张表,重温一下第四点,你会慢慢明白的。说实在的,这张表花了我不少功夫呢,幸好TeX画表格还算省事!
这张表里头有诸多有趣的地方,我提示一下:
★ 看 N 列,从上到下,二进制位表达是均匀递增的,且增量都是一种最小二进制位。这不是偶尔,正是巧妙设计的成果。观测最大的非规格数,发现正好就是M全为1, E全为0的状况。于是我们求出最大的非规格数为:
上面的公式中,h为M的位数(如范例中为3)。注意,公式等号右边的第一项同步又是最小规格数的值(如范例中为 8/512 );第二项则正是最小非规格数的值(如范例中为1/512)即该浮点数能表达的最小正数。
★ 看 m 列,规格化数都是 1+ x 的形式,这个1正是隐含位1; 而非规格化数隐含位为0, 因此没有 "1+" 。
★ 看 n 列,非规格化数从上到下的增量都是 1/512, 且过渡到规格化数时,增量是平滑的,仍旧是1/512。这正是非规格化数中e等于(1-bias)而不是(-bias)的缘故,也是巧妙设计的成果。 再继续往下看,发现增量值逐渐增大。可见,浮点数的取值范畴不是均匀的。
六、实战
我们用一小段汇编来测试一下,浮点数在内存中是如何表达的。测试环境: assembler version gdb XP1600+。 如下所示
   
代码:
   
~/coding/assemble $  gdb
(gdb) list
1    .section .data
2    f1:
3        .float  5
4    f2:
5        .float     
6    .section .text
7        .global _start
8    _start:
9        nop
10   
(gdb) x/f &f1
0x
80490a4 <f1>:    5
(gdb) x/xw &f10x80490a4 <f1>:    0x40a00000
(gdb) x/f &f20x80490a8 <f2>:    0.
(gdb) x/xw &f20x80490a8 <f2>:    0x3dcccccd
(gdb)
从上面的gdb命令成果可以看出,浮点数5被表达为 0x40a00000,二进制形式为( 0100 0000 1010 0000 ... 0000 0000)。红色数字为E,可以看出|E|=129>0, 则e=129-bias=129-127=2 ; 蓝色数字为M, 且|E|>0,阐明是规格化数,则m=||=|..000|= ; 由n的计算公式可以求得 n=(-1)^0 * * 2^2  = 5, 成果被验证了。