浮点型分为单精度浮点型(float)和双精度浮点型(double),二者的精确范围不一样,在计算机存储中各占4字节和8字节。
我们可以通过limits.h和float.h这两个头文件查看浮点型的精度和范围。
要想弄清楚浮点型如何在内存中存储,以及float和double的区别。首先要明确以下几点。
1.小数的二进制表示法。 如:十进制小数5.5 二进制表示为101.1
2.浮点型在计算机中存储遵循IEEE 754(二进制浮点数算术标准)
3.指数位决定取值范围,有效数字位决定计算精度
浮点数存储规则1.根据IEEE754标准,两种浮点型的格式参数如下
符号位S与整型存储相同,1代表负数,0代表正数,不同的是,浮点型不存在原码,反 码,补码的概念。
对于指数E和有效数字M,我们知道,任意小数可以使用科学计数法表示:
如十进制小数0.00005=5×10⁻⁵。同理,二进制小数101.1=1.011×2²
那么,根据IEEE754规定,1.011就代表有效数字M,2²的指数2代表指数E。
格式参数的可视化形式:
2.对于M和E,还有一些特别规定。
由于1≤M<2,即有效数字位可以写成1.xxxxxx的形式,那么我们可以把小数点前的1省略,只 将小数点后的数字存进去。读取时,再将1加上去。这样做的目的是为了多存储一位有效数 字。
对与指数E。float留了8位,double留了15位,范围分别为0~255,0~2047。但在科学计数法 中,指数存在负数的情况。所以IEEE754规定,存入内存时,E的真实值必须再加上一个中间 数。float中间数为127,double的中间数为1023。
相当于舍弃了符号位,但还是可以保存-127~128或-1023~1024的真实值范围。
接上一条,E存在全0和全1两种特殊情况,
E全为0:有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示 ±0,以及接近于 0的很小的数字。
E全为1:这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)。
例:将十进制0.5的二进制存入内存。
首先转换为二进制0.1,科学计数法写成1.0×2⁻¹,S=0,E=-1+127=126,M=0
有效数字23位要凑满,直接拿0凑
所以该数的二进制表示形式为:
0 01111110 00000000000000000000000
最后来道练习题:#includeint main() { int n = 9; float* pFloat = (float*)&n; printf("n的值为:%dn", n); printf("*pFloat的值为:%fn", *pFloat); *pFloat = 9.0; printf("num的值为:%dn", n); printf("*pFloat的值为:%fn", *pFloat); return 0; }
输出的结果是什么呢?
解释:
创建一个整型变量n=9,首先取地址转换成float*类型再放到指针变量pFloat中,这两步并没有改变n的值,所以n的值依然为9。
对pFloat进行解引用,由于之前9以整型存进去,所以n内存的是二进制00000000000000000000000000001000,而pFloat是float*类型,以%f形式打印,所以要以浮点型的视角来看,那么E全为0,最终结果就是0。
将9.0赋给*pFloat,9.0的二进制科学计数法为1.001×2³那么,S=0,E=3+127=130,M=001,M后面要拿0凑满,所以*pFloat为0 10000010 00100000000000000000000,又将其以%d的形式打印,也就是整型的视角来看这串二进制,内存中整型存的补码,正数原反补相同,通过计算器算出
与运行结果一致。
最后将其以%f的形式打印,类型一致,那么就打印9.000000。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)