float和double类型的内存分布和比较

本文详细解析了C/C++中float和double类型的内存布局及表示方式,包括符号位、指数和尾数的存储规则,以及如何正确比较浮点数。
C/C++的浮点数据类型有float和double两种。 
类型float大小为4字节,即32位,内存中的存储方式如下:


 符号位(1 bit)

指数(8 bit)

尾数(23 bit)


类型double大小为8字节,即64位,内存布局如下:


符号位(1 bit)

指数(11 bit)

尾数(52 bit)


  
符号位决定浮点数的正负,0正1负。 
指数和尾数均从浮点数的二进制科学计数形式中获取。 
如,十进制浮点数2.5的二进制形式为10.1,转换为科学计数法形式为(1.01)*(10^1),由此可知指数为1,尾数(即科学计数法的小数部分)为01。 
根据浮点数的存储标准(IEEE制定),float类型指数的起始数为127(二进制0111 1111),double类型指数的起始数为1023(二进制011 1111 1111),在此基础上加指数,得到的就是内存中指数的表示形式。尾数则直接填入,如果空间多余则以0补齐,如果空间不够则0舍1入。所以float和double类型分别表示的2.5如下(二进制):

浮点数2.5可以用二进制小数准确表示(2.5=1*(2^1)+0*(2^0)+1*(2^-1)),但很多小数不可以准确表示,其二进制形式的小数部分会无限循环,如浮点数-1.2表示如下(二进制):


符号位

指数

尾数

1

0111 1111

0011 0011 0011 0011 0011 010

1

011 1111 1111

0011 0011 0011 0011 0011 0011 0011 
0011 0011 0011 0011 0011 0011


由于对无限循环尾数的截取遵循0舍1入,尾数的第21~24位为0011,第53~56位为0011,而float尾数容量为23位,double尾数容量为52位,所以,float形式的最后三位因进位而成010,double形式则没有进位发生。 
  
类型float和double通过==,>,<等比较不会引起编译错误,但是非常可能得到错误的结果。这是因为它们的内存分布不同,不可以直接比较。正确的方法是转换为同一类型后比较两者差值,如果结果小于规定的小值,则视为相等。 
如,一个比较double的实现: 
http://metasharp.net/index.php?title=How_to_compare_double_or_float_in_Cpp 
另外,本文参考了如下webs: 
http://cdatatype.blogspot.com/2008/01/memory-map-of-floatdouble.html 
http://blog.youkuaiyun.com/hzb1983/archive/2007/09/24/1798555.aspx 
  
P.S. 
1) 
IEEE浮点数标准:     4字节浮点数:1位符号位,8位阶数(基数为127的移码),23位尾数;     8字节浮点数:1位符号位,11位阶数(基数为1023的移码),52位尾数 
2 ) 
在VC中: float数值范围约在 -10e38~10e38,并提供7位有效数字位,绝对值小于10e38地数被处理成零值 double数值范围约在-10e308~10e308,并提供15~16位有效数字,绝对值小于10e308地数被处理成零值 

符号位

指数

尾数

0

1000 0000

010 0000 0000 0000 0000 0000

0

100 0000 0000

0100 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 0000
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值