首页 > 编程语言 > 详细

C++中float类型的存储

时间:2014-03-23 22:08:42      阅读:557      评论:0      收藏:0      [点我收藏+]
C++中float用32位来表示,f = (-1)^S * T * 2^E,S是符号位,T是尾数,E是指数
bubuko.com,布布扣
bubuko.com,布布扣
首先我们把f表示成科学计数法的形式,然后再写出其在内存中的表示,在这里T写成1.XXX的形式,所以可以表示24位尾数
举例来说 f = 14.25f = (1110.01)B = (1.11001*2^3)B 所以符号位S = 0, T = 11001B, E = 3 = 11B
另外指数可以为负数,在C++中,是把指数加上127来存储的,即E= E+ 127 = 130 = 10000010B
即 
 bubuko.com,布布扣bubuko.com,布布扣bubuko.com,布布扣bubuko.com,布布扣bubuko.com,布布扣bubuko.com,布布扣
bubuko.com,布布扣
在x86系统中,小端模式,因此在内存中的存储为0x00|00|64|41
 
那么我们可以计算一下C++中float表示的范围了,可以先列出S,T,E的取值范围
S = 0 或者1
T = 最小0 最大 1-2^32
S = 最小-127 最大128
绝对值最大为 ABSMAX = [1-(2^-32)]* 2^128 约等于 3.4E+38
绝对值最小为  ABSMIN = 1.0 * 2^(-127)
所以取值范围是 [-ABSMAX, -ABSMIN] 和 [ABSMIN, ABSMAX]
 
另外对于0.0f,内存中是以全0表示
 
附float与int之间的转换,首先需要说明的是int与char在C++中都是以补码形式存储
int->float 
把int写成科学计数法形式,比如 i = -128 = -1.0*(2^7) B 所以符号位S = 1, T = 0B, E = 7 = 111B
E = E+ 127 = (10000110)B
在x86系统中,小端模式,因此在内存中的存储为0x00|00|00|C3,而int类型的存储为0x80|ff|ff|ff(补码形式)
注意在整个过程中int要进行右移操作,int有1位符号位,31位数字位,但是float只有24位尾数,所以可能造成精度下降
float->int
int表示的范围是[-2^31, 2^31-1],因此只是落在此范围中的float转成int有实际意义,否则结果是未可知的
float数字位f = (-1)^S * T * 2^E, 令T = 1.T,然后根据指数E对T进行移位操作即可,最后根据符号位S判断结果的正负
对于f = 0,内存中以全0表示,需要单独处理
代码如下
bubuko.com,布布扣
float f = 40;
 //*(int *)(&f) = 0xFFFFFF;
 int p = *(int *)&f;
 //尾数 当然与真实的尾数左移了23位
 int t = (p & 0x7FFFFF) | 0x800000;
 //指数
 int e = (p >> 23) & 0xFF;
 //符号位
 int s = p >> 31;
 if(e - 127 < -31 || e - 127 > 31)
 {
  printf("结果不可知\n");
 }
 e = e-127-23;
 if(e > 0)//左移
  p = t << e;
 else if(e < 0)//右移
  p = t >> -e;
 if(s < 0)
  p = -p;
 if(f == 0)
  p = 0;
bubuko.com,布布扣

 

在上述代码中,不管是左移还是右移当移动次数大于等于32时,会得到意想不到的结果,实际上有如下结论
如果被移动对象的长度是n位,那么移动计数必须大于等于0,并且严格小于n。
对于宽度为m的类型, 在X86上运行,移动次数为n,若n>=m,结果相当于移动 n&(m-1) 次
若n < 0, 则存在最小的k,使得k*m + n = n‘ > 0,相当于移动n‘次
 
 

C++中float类型的存储,布布扣,bubuko.com

C++中float类型的存储

原文:http://www.cnblogs.com/rain-lei/p/3619173.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!