int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
结果为:
n的值为:9
*pFloat的值为:0.000000
num的值为:1091567616
*pFloat的值为:9.000000
中间两行看似奇怪的结果,其深层就是浮点数的存储与整形有很大的不同
上图是浮点数float的存储形式,总共32个字节,S代表符号位,E代表指数位,M为有效数字
以5.5为例
将5.5转为二进制会变为101.1,因为2^2+2^0+2^-1=5.5
在浮点数中,它的存储形式为0 10000001 011000000000000000000000
至于原因为何,且听我慢慢道来
首先先看符号位
0代表正数,1代表负数,即(-1)^0=1为正 (-1)^1=-1为负
对于指数位
首先我们要知道,在存储之前101.1会转变为1.011>>2即1.011*2^2 类似于科学计数法
而2的指数就是指数位 但是我们知道如果数字为0.5之类的数用如上方法表示会变成1*10^-1,即指数可能为负,所以在存储时我们会将指数加上127(与整形对负数的处理要区分开)这样即可表示【-127,128】的指数。2+127=129,用二进制则为10000001。
对于有效数字
有效数字即是1011,但由于首位总为1,因此在存储时会省略1,存储011,这样可以多出一个有效数字位。
现在想必大家对于5.5的结果应该是了解了,那么存储之后,编译器是如何识别出0 10000001 011000000000000000000000是5.5的呢?
符号位想必不用说,对于指数位首先会-127,使之变回原来指数,对于有效数字会在前面加一
最后以(-1)^0 * (1.011)>>2转为10进制算出结果为5.5
现在我们回去看上面的结果来监测一下是否掌握了浮点数的存储
9的符号位为0 二进制为1001,用类似科学计数法变为1.001>>3 及有效位0010......0
指数位3+127,即10000010
即0 10000010 0010......0 转为十进制即为1091567616
而整形9为00000000.....1001 转为浮点数符号位为0,指数位为-127,有效数字为0000000.....1001
无限接近于0,最后输出0。事实上,这就是为什么浮点型与0比较不能直接用==的原因