计算机中浮点数类型的存储

来源:互联网 发布:网络舆情管理工作总结 编辑:程序博客网 时间:2024/04/28 00:38

快速入门

根据IEEE的标准,浮点数的定义如下

符号位s

指数位e

小数部分x

指数偏移量

单精度浮点数

[31]

8位 [30-23]

23位 [22-00]

127

双精度浮点数

[63]

11 [62-52]

 52 [51-00]

1023

对于32bit的浮点数(32bit为单精度,64bit浮点数为双精度,80bit为扩展精度浮点数)

1、其第31 bit为符号位,为0则表示正数,反之为复数,其读数值用s表示;

2、第3023 bit为幂数,其读数值用e表示;

3、第220 bit23 bit作为系数,视为二进制纯小数,假定该小数的十进制值为x

十进制转浮点数的计算方法:则按照规定,十进制的值用浮点数表示为:

如果十进制为正,则s = 0,否则s = 1;将十进制数表示成二进制,然后将小数点向左移动,直到这个数变为1.x的形式即尾数,移动的个数即位指数。为了保证指数为正,将移动的个数都加上127,由于尾数的整数位始终为1,故舍去不做记忆。

3.141592654来说,

1、正数,s = 0

23.141592654的二进制形式为正数部分计算方法是除以二取整,即得11,小数部分的计算方法是乘以二取其整数,得0.0010 0100 0011 1111 0110 1010 1000,那么它的二进制数表示为11.0010 0100 0011 1111 0110 1010 1

3、将小数点向左移一位,那么它就变为1.1001 0010 0001 1111 1011 0101 01,所以指数为1+127=128e = 128 = 1000 0000

4、舍掉尾数的整数部分1,尾数写成0.1001 0010 0001 1111 1011 0101 01x = 921FB6

5、最后它的浮点表示为01000 00001001 0010 0001 1111 1011 0101 = 40490FDA

浮点数转十进制的计算方法:

则按照规定,浮点数的值用十进制表示为: 

= (-1)^s  * (1 + x) * 2^(e - 127)

对于49E48E680100 1001 1110 0100 1000 1110 0110 1000来说, 

1、其第31 bit0,即s = 0

2、第3023 bit依次为100 1001 1,读成十进制就是147,即e = 147。 

3、第220 bit依次为110 0100 1000 1110 0110 1000,也就是二进制的纯小数0.110 0100 1000 1110 0110 1000,其十进制形式为(0.110 0100 1000 1110 0110 1000 * 2^23) / (2^23) = (0x49E48E68 & 0x007FFFFF) / (2^23) = (0x648E68) / (2^23) = 0.78559589385986328125,即x = 0.78559589385986328125。 

这样,该浮点数的十进制表示 

= (-1)^s  * (1 + x) * 2^(e - 127)

= (-1)^0  * (1+ 0.78559589385986328125) * 2^(147-127)

=    1872333

 

 

以下是几个概念:
1规格化计数法

用科学计数法表示实数时,如果最左边的第一个数字不是0,则被称为规格化计数法

0.1   × 10-2  不是规格化计数法

1.0   × 10-3  则是规格化计数法

 

2、浮点数不能用==号来判断是否相等,因为存在一个精度问题。

3、原,反,补,移码。对于正数而言,原、反、补码都一样。对负数而言,反码除符号位外,在原码的基础上按位取反;补码则在反码的基础之上,在其最低位上加1;移码其实就等于补码,只是符号相反,要求移码时,仍然是先求补码,再改符号

 

4基于IEEE 754的浮点数存储格式IEEEInstitute of Electrical and Electronics Engineers电子电气工程师协会)在I985年制定的IEEE 754IEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Std 754-1985 )二进制浮点运算规范,是浮点运算部件事实上的工业标准。80年代起所有的计算机系统均支持IEEE 754

1)对于规格化二进制浮点示法而言,有效数位的第1位必定是1而不是0,因此,IEEE 754 规定:实际有效数位中的第1位被省去,因而,有效数位中默计含有1位。

2)移码:除了将指数安排在有效数位前面,还不足以快速比较两个浮点数的大小,例如:

1.0 × 2^-1 在计算机中表示为:0 11111111 00000000000000000000000

这个数相当于整数的 0x7F800000

1.0 × 2^1 在计算机中表示为:0 00000001 00000000000000000000000

这个数相当于整数的 0x00800000

如果用整数比较指令,比较两个数,1.0 × 2^-1  竟然比 1.0 × 2^1  还大!

为了解决这个问题,IEEE 754 设计了一个方案:将指数加上一个常数 127

这个常数 127 被称为“移码”(biased notation

我们再来看一看:

1.0 × 2^-1 将指数: -1 + 127 = 126 ,得出以下的二进制数:

0 01111110 00000000000000000000 也就是: 0x3F000000

1.0    × 2^1 将指数:1 + 127 = 128 后,得出以下的二进制数:

0 10000000 00000000000000000000 也就是:0x40000000

这样的话,就可以得出正确结果了。

 

5、浮点数分为floatdouble,分别占48个字节,即3264位。 我仅以32位的float为例,并附带说double

IEEE754标准中,规定float32位这样分

符号位(S

阶码(E

尾数(M

1

8

23

这里应该注意三点: 

A,阶码是用移码表示的,这里会有一个127的偏移量,它的127相当于0,小于127时为负,大于127时为正,比如:10000001表示指数为129-127=2,表示真值为2^2,而01111110则表示2^(-1)。 

B, 尾数全都是小数点后面的数,

C, 但尾数中省略了一个1,因此尾数全为0时,也是1.0...00

接下来只要说明几个问题就明白了,以123.456为例,表示为二进制就是:N (2) = 1111011. 01110100101111001 ,这里,会右移6位,得到N (2) = 1.111011 01110100101111001*2^6; 这种形式就可以用于上图中的表示格式了。

符号位(S

阶码(E

尾数(M

0

00000110

11101101110100101111001

注意到,上面的阶码第一位为0表正,尾数比N(2)表示的第一位少了个1,这就是上面说的默认为第一位为1。 由于在将十进制转为二进制的过程中,常常不能正好转得相等, (当然,像4.0这样的就不会有损失,而1.0/3.0这样的必然损失),所以就产生了浮点数的精度问题, 实际上,小数点后的23位二进制数,能影响十进制数的前8位。小数点后有23位,最后一位的值为1时,它就是1/2^22=0.000000238实际取的时候肯定是0.0000002,也就是说,对于一个float型的浮点数,其有效的位数是从左到右数7(包括缺省的1才是7),当到达上面这个第8位时,就不可靠了,但我们的VC6可以输出最长的1.0/3.0033333333333333331,这主要是编译器的问题了, 而并不是说浮点数小数点后的16位都有效。 如果不信的话,可以去试一下double类型的1.0/3.0, 得到的也将是小数点后17位。另外,编译器或电路板一般都有"去噪声""修正"能力,它能够使得超过7位的十进制数即使无效了也不会变得离谱,这也是上面为什么一直都是输出333而不是345之类的,可以这样试一下:

float f=123456789

cout<<f<<endl//这里肯定得到123456789。 

 

下面说示数范围。

阶码的示数位数是8位移码,最大为127最小为-127,这里的127用来作为2的指数,因此为2^127,约等于 1.7014*10^38, 而我们知道,float的示数范围约为-3.4*10^38-------3.4*10^38, 这是因为尾数的24(默认第一位为1)全为1时,非常接近2, 1.11..11(二进制)很明显约为2(十进制),因此浮点数的范围就出来了。

 

 

6、再来几个例子巩固一下:

1、将 -0.625 转化为计算机中的二进制数浮点数

解:

-0.625 = -5/8 = -5/23  = -101 × 2-3  = -1.01 × 2-1

符号位:1

指数位:-1 + 127 = 126

有效数位:1.01(在机器中要相应去掉默认位)

所以,在机器表示的二进制序列为:1 01111110 0100000000000000000000

相当于整数:0xBF200000

2、将如下二进制序列用十进制浮点数表示。

11000000101000000000000000000000

解:

符号位:是负数

指数位;10000001 = 129, 这个数要减去移码值,即:129 – 127 = 2

有效数位:01000000000000000000000 这个数要加上默认1,即得:1.01

整个序列结果为:- 1.01 × 22   = -101 = -5.0 

 

以下是我参考的多篇文章:

http://blog.163.com/china_2008ay/blog/static/9014225220102256406767/

http//blog.sina.com.cn/s/blog_6ca385a10100rr45.html

http://blog.sina.com.cn/s/blog_6f95aee601012pv6.html