5.浮点型在内存中的存储
先来看几个常见的浮点数
3.1415926
1E10 (1*10^10)
浮点数家族包括:float,double,long double
浮点数的表示范围在float.h中定义,整型的在limits.h中
-- -- -- -- -- -- -- -- -- -- -- -- -- -- --
引例
#include <stdio.h>
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
*pFloat = 9.0;
printf("%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
return 0;
}
运行结果:
n的值为:9
*pFloat的值为:0.000000
1091567616
*pFloat的值为:9.000000
规定
规定1
- (-1)^S * M * 2^E
- (-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数
- M表示有效数字,大于等于1,小于2 (1≤M<2)
- 2^E表示指数位,E是阶码
如引例中的9:
十进制:9.0(正)
二进制:1001.0 ——> 1.0010*2^3
=>(-1)^0*1.001*2^3
可以看一下图示
-- -- -- -- -- -- -- -- -- --
规定2
IEEE754规定:对应32为浮点数(float),最高位是符号位S,接着8位是指数E,剩下的32位是有效数字M
-- -- -- -- -- -- -- -- -- --
规定3
IEEE754 对有效数字M和指数E还有一些特别的规定,前面说过,1≤M≤2,即M总可以写成1.xxxxxx的形式,其中xxxxxx为小数部分
因为1总是出现,所以保存时只保存xxxxxx(小数部分),读取时再把1加回去,这样可节省一位有效数字,从而增加精度。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字
-- -- -- -- -- -- -- -- -- --
规定4
关于指数E,它的情况就比较复杂。首先E是一个无符号整数(unsigned int),这意味着如果E为8为,它的取值是0~255(本章第二节讲过);如果E为11位,它的取值是0~2047.但是,我们知道,科学计数法中E是可以出现负数的。所以IEEE754规定,存入内存时E的真实值必须再加上一个中间数(偏移量),对于8位的E(float),这个中间数是127;11位的E(double)则是1023
所以对于上面这个数的指数位存入内存中的就是10001001
-- -- -- -- -- --
而再我们将E从内存中取出时又可以分为三种情况
1.在E中0和1都有
这时,浮点数的表示规则为,指数E的计算值减去127(或者1023),得到真实值,再将计算出来的有效数字补上以前去掉的1
2.E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字不再加上以前去掉的1,而是还原成一个0.xxxxxx这样的小数。这样做的原因是为了表示±0、以及接近0的很小的数字
3.E全为1
这是,如果有效数字M全为0,表示±无穷大(具体正负取决于符号位S)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- --
回头看
到这里,关于数据的存储这一章就算是结束了,不过我们再回头来看看本节开头引例中的那个例子,现在学完浮点型在内存的存储之后能不能解释那段代码的运行结果了
引例代码
#include <stdio.h>
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
*pFloat = 9.0;
printf("%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
return 0;
}
9:存入整型,打印整型就是9
0.000000:存入整型,打印浮点型。(十进制)9—>(二进制)0 00000000 000...0001001, 我们可以发现,9转换成二进制它的E全是0(取出时应该用第二种情况的规则)。等于(-1)^0 × 0.000000 00000000000001001×2^(-126)=1.001×2^(-146),由于在打印时计算机只会打印小数点的后6位,所以结果位0.000000
1091567616:存入浮点型,打印整型。首先,浮点数9.0等于二进制的1001.0,即1.001×2^3
那么,第一位S=0,有效数字M=001后面再加20个0,凑满23位
指数E等3+127=130, 即10000010。所以,写成二进制形式,应该是s+E+M,即这个32位的二进制数,还原成十进制,正是 1091567616
9.0:存入浮点型,打印浮点型就是9.000000