浮点型数据存储格式详解
本文是对 Computer Systems__A Programmer's Perspective 一书中 Chapter2__2.4 Floating Point一节的理解
在1985年之前,每个pc制造商都有自己的浮点数表示和计算方法。那时更让人关心的是浮点数的计算速度和实现方法而非数值和计算的精度。在1985年,IEEE标准进行了统一,提升了程序的可移植性。
生活中常用的是10进制表示的数值,dmdm-1…d1d0.d-1d-2…d-n表示如下:
d0与d-1间的小数点“.”,表示该符号左边的数值10的指数是正数,右边的数值10的指数是负数。
同理,考虑一个2进制表示的数值,bmbm-1…b1b0.b-1b-2…b-n表示如下:
其中,bi只能是0或1。同时,小数点“.”符号左边的数值2的指数是正数,右边的数值2的指数是负数。比如,101.112表示1*2^2+ 0*2^1 + 1*2^0 + 1*2^-1 + 1*2^-2 = 4 + 0 +1 + 1/2 + 1/4 = 5 + 3/4。
通过2进制数值的表示方式,可知将小数点符号“.”向左或向右移位,分别表示原有数值除2或乘2。10.1112的数值是2 + 7/8,1011.12表示11 + 1/2。
数值的X进制的编码不可能是无限长的,因此一些数值受限于编码长度只能近似表示而不能完全精确。如1/3、5/7的10进制在编码长度一定时,就不能完全精确表达该数值;1/5在2进制表示下只能通过增加编码长度无限逼近该值。这就是浮点数精度产生的原因:在计算机中,因为2进制编码长度的限制,浮点数中小数点后的部分数值因为不能表示而被丢弃。基于这个原因,就可以理解浮点数比较为什么不和整形数值之间的比较一样,直接用“<”、“>”、“==”等运算符得到数值间的大小,而一定要用if (a-b<0.000001)条件来判断了。
IEEE标准中的的浮点数表示形式为V = (-1)s * M * 2E,
S—符号位,s为0时,浮点数大于0;s为1时,浮点数小于0。当浮点数为0.0时,s当作特殊情况处理,具体请看下面说明
E—指数位,2的指数数值
M—数值位,小数的2进制数值,范围为0—1或1—2
对应浮点数的表示形式,浮点数的bits分为三部分:
S—符号位,占用1 bit
E—指数位,占用k bits,exp = ek-1…e1e0
M—数值位,占用n bits,frac = fn-1…f1f0,M的解译取决于E是否为0
32 bits的单精度浮点数(C语言中的float型)中s,k,n分别为1,8,23; 64 bits的双精度浮点数(C语言中的double型)中s,k,n分别为1,11,52。
浮点数的解译依据E的不同,分为三种情况:
Normalized values常规数值:
E中的bit位不全为0,也不全为1,大部分浮点数属于这此类。这种情况下E以biased form(偏差形式)解译为signed integer。Biased form为:
E = e – Bias
e是exp = ek-1…e1e0的unsigned number;Bias是偏差值,计算方式为Bias = 2k-1-1(单精度为127,双精度为1023)。E的范围是单精度为-126—+127,双精度为-1022—+1023。
M数值占用的n bit被解译为2进制的小数f(0 <= f < 1),即0. fn-1…f1f0。M = 1 + f,可以把M看作为2进制的1. fn-1…f1f0。在V = (-1)s * M * 2E表示形式中,可以调整E的大小保证1 <= M < 2,所以2进制的1. fn-1…f1f0的1可以去掉,增加小数部分的值用以提升数据精度。
Denormalized values非常规数值:
E中的bit为全为0,E以denormalized form(非常规形式)解读。Denormalized form为:
E = 1 – Bias,M = f。
非常规数值有两种用途:第一,可以表示0.0。在常规数值中,M始终是>=1的,不可能产生0.0。+0.0时,所有的bit值都是0,即符号位s为0,E的bit为0,M=f=0。当-0.0时,符号位s为1,其他的bit都是0。在IEEE浮点数格式中,-0.0与+0.0是否相同取决于应用场景。第二,可以表示接近0.0的数值。
Special Values特殊值:
当E中的bits全部为1时,M的bits全部为0时,表示无穷大,s=0时为正无穷+oo;s=1时为-oo。无穷可以表示数值的溢出,如两个很大的数相乘,或者除0;当M中的bit不全为0时,表示为NaN(Not a Number),即不是一个数。当操作的结果不能作为实数或者无穷返回时,就返回NaN,如计算或者oo-oo;NaN在某些应用中可以用来表示未初始化的值。
IEEE Floating-Point总结为下图