计算机中浮点数类型的存储
来源:互联网 发布:网络舆情管理工作总结 编辑:程序博客网 时间:2024/04/28 00:38
快速入门:
根据IEEE的标准,浮点数的定义如下:
符号位(s)
指数位(e)
小数部分(x)
指数偏移量
单精度浮点数
1 位[31]
8位 [30-23]
23位 [22-00]
127
双精度浮点数
1 位[63]
11 位[62-52]
52 位[51-00]
1023
对于32bit的浮点数(32bit为单精度,64bit浮点数为双精度,80bit为扩展精度浮点数)
1、其第31 bit为符号位,为0则表示正数,反之为复数,其读数值用s表示;
2、第30~23 bit为幂数,其读数值用e表示;
3、第22~0 bit共23 bit作为系数,视为二进制纯小数,假定该小数的十进制值为x;
十进制转浮点数的计算方法:则按照规定,十进制的值用浮点数表示为:
如果十进制为正,则s = 0,否则s = 1;将十进制数表示成二进制,然后将小数点向左移动,直到这个数变为1.x的形式即尾数,移动的个数即位指数。为了保证指数为正,将移动的个数都加上127,由于尾数的整数位始终为1,故舍去不做记忆。
对3.141592654来说,
1、正数,s = 0;
2、3.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=128,e = 128 = 1000 0000;
4、舍掉尾数的整数部分1,尾数写成0.1001 0010 0001 1111 1011 0101 01,x = 921FB6
5、最后它的浮点数表示为01000 00001001 0010 0001 1111 1011 0101 = 40490FDA
浮点数转十进制的计算方法:
则按照规定,浮点数的值用十进制表示为:
= (-1)^s * (1 + x) * 2^(e - 127)
对于49E48E68(0100 1001 1110 0100 1000 1110 0110 1000)来说,
1、其第31 bit为0,即s = 0
2、第30~23 bit依次为100 1001 1,读成十进制就是147,即e = 147。
3、第22~0 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的浮点数存储格式,IEEE(Institute of Electrical and Electronics Engineers,电子电气工程师协会)在I985年制定的IEEE 754(IEEE 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、浮点数分为float和double,分别占4,8个字节,即32,64位。 我仅以32位的float为例,并附带说double。
在IEEE754标准中,规定float的32位这样分
符号位(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.0为0。33333333333333331,这主要是编译器的问题了, 而并不是说浮点数小数点后的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
解:
符号位:1 是负数
指数位;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
- 计算机中浮点数类型的存储
- 计算机中浮点数的存储
- 计算机中浮点数的存储方式
- 计算机中浮点数存储
- 浮点数在计算机内存中是如何存储的?
- 浮点数在计算机内存中是如何存储的?
- 浮点数在计算机中存储的方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中如何存储
- 浮点数在计算机中如何存储
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 浮点数在计算机中存储方式
- 怎么学习数字图像处理
- 很多很多计划都搁浅了
- JAVA下的日历表
- 解决虚拟机提示:VMware Taking ownership of this virtual machine failed
- Cassandra简介及其压缩机制
- 计算机中浮点数类型的存储
- 从谷歌宕机事件认识互联网工作原理
- poj1060
- ubuntu 下root用户无法访问声音设备的解决方案
- 如何判断字符串中值的类型并将其转换成对应变量类型
- Thinking In Java 学习笔记(一)
- 推荐给开发人员的实用命令行工具
- android lanucher
- Android数据手册:Android颜色码制表