最近在读csapp,IEEE浮点表示当初捋了好久才理顺,算是第一章中比较难的部分了。
通过普通的定点表示法不能有效表示非常大的数字。例如表达式5*2^100是101后面跟了100个0,我们希望使用一种更简洁高效的办法表示,IEEE浮点表示应运而生。
以下是将会出现的符号含义
V:你要表示的十进制数。
S:符号位,0表示这是个正数,1表示这是个负数。
M:尾数,代表这个数的小数部分,它可能是0.XXXXXXXXXX·····或1.XXXXXXXXXXXX······
E:阶码,对这个数加权,这个权重是2^E
以及在推导时使用的一些约定俗成的过程量:
s:二进制表示时的符号位,和S一样。
f(frac):推导过程的小数字段,用它来推导M。
e(exp):推导过程的阶码字段,配合bias来推导E
bias:偏置量,保证0.XXXXXX与1.XXXXXXXX所代表的两种格式中的平滑过度。
在计算机中这种表示法的占位如图:
前文提到的0.XXXXXXXXXx和1.XXXXXXXX实际上是两种IEEE表示的情况
规格化与非规格化:
1.规格化。
规格化表示的是阶码不全为0,也不全为1的情况,表示大部分情况,1.XXXXXX并不是指代它大于1,而是指代它不那么接近0,所以它的小数字段始终为1.XXXXXX。
先明白如何将一个规格化的浮点转化为10进制小数。
我们用0 1001 111这个浮点数来示例,其中第一个0是符号位,表明它是一个
非负数,然后的1001是阶码字段e,然后111是尾数字段f,也就是二进制小数。
首先求出bias偏置值,bias=
其中k是e的位数,在这里k=4,因此bias等于7。
然后将e转化为无符号数,这里e是9
然后求E,在规格化中,E=e-bias,这里E等于2
然后让我们看看浮点数的计算公式
还要求个M,M使用小数字段f转化的来,但要注意,因为规格化中默认小数字段为1.XXXX
所以在f中不表示这个“1”的存在,因此将小数字段转化为十进制小数后要加1。
在这个示例中,小数字段M为7/8+1=15/8。
然后把s,M,E带入公式,就可以得到V=15/2=7.5。
2.非规格化
非规格化表示的是阶码全为0的情况,表示这个数十分接近0或者就是0的情况,此时小数字段表示的就是0.XXXXXXXXX了
计算方法和规格化略有不同,但依然是将E,M计算出后带入公式
E在非规格化中等于1-bias,M转化为十进制小数,这次不用对M做处理了。
然后将它们带入公式。
3.特殊值
这个表示阶码全为1的情况,当小数字段全为0时,这个值表示无穷大,s=0是
正无穷,s=1是负无穷,当我们把两个非常大的数相乘,或者除以零时,无穷
表示溢出的结果。当小数字段非0时,表示运算结果不能是实数或无穷,用NaN表示,
比如求一个负数平方根。
那么如何将一个十进制数转化为浮点表示呢,我们用100.25这个数做一个示范,转化结果为float类型浮点数:
首先将100.25化为二进制定点表示:1100100.01
然后移动它的小数点,使其符合标准:1.10010001*2^6
把它和
对比,发现6就是E,我们根据E可以推出它的阶码字段e
Bias=127(float类型阶码字段为8位)
E=e-bias,所以e=bias+E=133,再把e转化为二进制数:10000101,这就是阶码字段
很明显这是一个规格化表示,所以把1.10010001小数点左侧的1去了,得到10010001,这就是小数字段
然后把符号位,阶码字段,小数字段依次组合,得到01000010110010001,但我们要求的是float类型,所以要把位数补全到32位,在最后补17个0,就得到了100.25的float类型浮点数。