C++中float类型的存储
2014-03-23 16:04
288 查看
C++中float用32位来表示,f = (-1)^S * T * 2^E,S是符号位,T是尾数,E是指数
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/c8db0e92330cc82d85bf726b3b0ccb15.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
首先我们把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
即
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/6271d1cd820ee78d215e88003461984c.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/4636c1c3db93426d9ce9057ed14e0d06/clipboard.png)
在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表示,需要单独处理
代码如下
在上述代码中,不管是左移还是右移当移动次数大于等于32时,会得到意想不到的结果,实际上有如下结论
如果被移动对象的长度是n位,那么移动计数必须大于等于0,并且严格小于n。
对于宽度为m的类型, 在X86上运行,移动次数为n,若n>=m,结果相当于移动 n&(m-1) 次
若n < 0, 则存在最小的k,使得k*m + n = n' > 0,相当于移动n'次
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/c8db0e92330cc82d85bf726b3b0ccb15.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
首先我们把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
即
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/64c66905160b48b3940f7f2dd8191da8/clipboard.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/30/6271d1cd820ee78d215e88003461984c.png)
![](http://www.cnblogs.com/rain-lei/p/file:/F:/%E4%BA%91%E7%AC%94%E8%AE%B0/tiandelei2008@163.com/4636c1c3db93426d9ce9057ed14e0d06/clipboard.png)
在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表示,需要单独处理
代码如下
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;
在上述代码中,不管是左移还是右移当移动次数大于等于32时,会得到意想不到的结果,实际上有如下结论
如果被移动对象的长度是n位,那么移动计数必须大于等于0,并且严格小于n。
对于宽度为m的类型, 在X86上运行,移动次数为n,若n>=m,结果相当于移动 n&(m-1) 次
若n < 0, 则存在最小的k,使得k*m + n = n' > 0,相当于移动n'次
相关文章推荐
- c++ float类型小端转大端存储
- c/c++中float和double类型的存储
- C++ 作用域与存储类型及预编译指令及文件结构
- float类型存储的浮点表示法
- c++中的存储类型
- 关于C++中string对象向int、float、double类型的转换的方法汇总
- C++ static class 存储类型
- c++基础:const,变量的作用域和生存期,存储类型
- C++存储类型
- C语言:自己动手查看float以及double类型的变量2.5在内存中的存储方式。
- Dev-C++下关于float/double类型的实验
- 浮点性(float)转化为字符串类型 自定义实现和深入探讨C++内部实现方法
- C++:存储类型
- C++中将string类型转换为int, float, double类型
- 存储类型、作用域、可见性和生存期C++
- C/C++中int/long/float/double数值类型与字符串互相转换[总结]
- 准确详解:C/C++ float、double数据类型的表示范围及精度
- C++中类型空间及所能存储的最大值
- C\C++中变量的存储类型
- 单精度类型(float)和双精度类型(double)存储