浮点数在计算机中存储的方式

来源:互联网 发布:mac finder 打开路径 编辑:程序博客网 时间:2024/04/28 03:44

浮点数在计算机中的存储

1996年6月4日,欧洲最新的无人驾驶火箭Ariane5初次航行时,发射后仅37秒,火箭偏离了它的飞行路径,解体并且爆炸。火箭上载有价值5亿美元的通信卫星。科学家们进行调查之后,原来只是因为小小的浮点数导致这场灾难性的后果,白白地损失了5亿美元。
作为这场事故的肇事者浮点数,它转换成整数时发生了溢出。在Ariane5的控制惯性导航系统的计算机向控制引擎喷嘴的计算机发送了一个无效数据,本应该发送飞行控制信息,而是发送了一个诊断位模式。表明将一个64位浮点数转化成16位有符号整数时,产生了溢出。
现今计算机都采用IEEE标准下的浮点数规则,方便在不同机器上的可移植性。

一.浮点数的表示:

IEEE浮点标准表示:V=(-1)^s*M*2^E。

符号(sign):s决定这个数是负数(s=1)还是正数(s=0)
尾数(significand):M是一个二进制小数
阶码(exponent):E的作用是对浮点数加权,权重是2的E次幂
将一个浮点数的位分解成3个字段,分别对这些字段进行编码:
1. 单独的符号位s占1位;
2. k位的阶码字段exp编码阶码E;
3. n位小数字段frac编码尾数M.
C语言中的float,s占1位,k占8位,n占23位,加起来32位,即4个字节。double类型的s同样占1位,只是k和n占的位数和float不同,但是计算方式一样。以下例子以float为准。
例子1:浮点数125.125D = 1111101.001B,转化规则为:先将二进制小数用二进制科学记数法表示,即1.111101001*2^6,指数E=6,因为该数为正,所以符号位s=0,由于k=8,因此偏移量Bias=2^(k-1)-1=127,所以阶码字段e=E+Bias,为133,即10000101。M=1.111101001,frac表示尾数,即科学计算法小数点后面的部分,不足23位补0。因此32位浮点数125.125在计算机中表示为01000010111110100100000000000000。8位的指数可以表示0-255指数值,但是如果指数为负则表达不了,所以Bias存在的原因为了处理指数为负的情况,这样可以表达的指数值范围就变成了[-127,128]之间。即exp=E+Bias。
浮点数在IEEE标准下又分为3类:
1. 规格化的值:当exp阶码字段不全为0也不全为1。M=1+frac。上面的例子既是规格化的值。
2. 非规格化的值:exp阶码字段全为0时,在这种情况下,实际的E=0,但是表示时为E=1-Bias而不是E=0-Bias,这是为了更加平滑地将非规格化值转化为规格化值。M=frac。
3. 特殊值:exp阶码字段全为1时称为特殊值。当小数域全为0时,得到的值为无穷。小数域为非零时,结果值称为NaN,不是一个数,比如根号-1。
平滑地将非规格化值转化为规格化值解释:
假如k=4,n=3,最大的非规格数为0 0000 111,由此可得E=1-(2^(k-1)-1)=-6,2^E=1/64,frac=1/2+1/4+1/8=7/8,M=frac,所以V=(-1)^0*2^E*M=7/512。最小的规格数为0 0001 000,E=1-(2^(k-1)-1)=-6,2^E=1/64,frac=0/8,M=1+frac=1。V=8/512。
最大的非规格数为7/512,最小的规格数为8/512,完成了平滑的转换,如果非规格数种E=-Bias,那么最大的非规格数应该为7/1024。
非规格数有两个作用:
1. 可以表示0
2. 表示那些非常接近0.0的数,非规格数在最小规格数和0之间可以表示大量的小数。

二.舍入

IEEE标准表示的浮点数限制了浮点数的范围和精度,,因为需要将值x匹配到对应的x’,这就是舍入
IEEE浮点格式定义了4中不同的舍入方式,默认的舍入方式是找最近的匹配。其它3种分别为向上舍入、向下舍入、向零舍入。
最近匹配:又称向偶数舍入。找到一个最接近的匹配值,比如1.2舍入为1.0,但是如果是两个可能的中间值的话就需要一种判断方法,定义为总是向最低有效数字为偶数舍入。比如1.5舍入成2.0。这种方法运用于二进制小数时,最低有效位的值0认为是偶数,1认为是奇数。比如舍入到小数点后2位(最近的匹配值为1/4,即每次按1/4来舍入),10.00011(2*(3/32))向下舍入为10.00(2),10.11100(2*(7/8))向上舍入成11.00(3)。

三.浮点运算

浮点数的运算计算出来的值其实并不是算出来是多少就是多少,因为浮点数表示的范围和精度都有限,所以会进行舍入,匹配到一个值。举个例子,假如0.1+0.2=0.3,但是浮点数的表示中没有0.3这个值,那它会将0.3按最近匹配匹配到一个可以表示的值进行输出。所以在程序中,这种误差如果累积下来,计算出来的结果可能偏差会极大。另外浮点加法不具有结合性,即(a+b)+c不一定等于a+(b+c),因为过程中可能会出现舍入。浮点乘法不具有结合性和分配性,原因也是舍入或者溢出。

总结:

回到Ariane5爆炸的原因,浮点数为64位,k=11,既可以表示2^(e-Bias)这么大,Bias=2*(k-1)-1=2013,即可表示2^(2^12-1-2-13)=2^128次方,有符号整数为16位,最大可以表示2^15-1。只要速率变大,会溢出是很正常的事,所以说。。。。老司机要注意速度,不要动不动就飙车,哈哈。

0 0
原创粉丝点击