浮点数的存储

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比较不能直接用==的原因


版权声明:本文为m0_61016568原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。