浮点数在计算机内存中的存储方式

我们知道,对于一个整数,在计算机内存中是以二进制的形式来存储的,但对于一个浮点数尼?假如仍以浮点数的二进制来存储,那小数点的位置如何来固定尼?所以人们就想到可以用二进制的科学计数法来保存,例如:5.5,其二进制数为101.1,则用二进制的科学计数法可以表示为 1.011 * 2^2,这样小数点的位置就是固定的。

任何一个浮点数可以表示为下面的形式(国际标准IEEE 754):

  • (-1)^S * M * 2^E
  • (-1)^S表示符号位,当S=0时,为正;当S=1时,为负
  • M表示有效数字,M>=1且M<2
  • 2^E表示指数位

上面的例子中,S=0,M=1.011,E=2。
所以当存储浮点数时,只需要将上述三个数字保存起来,就可以了。
对于但精度浮点数,其存储模型为:

这里写图片描述
对于双精度浮点数,其存储模式为:
这里写图片描述

其中,S只可能为0或者1,所以只需用一个bit位即可保存。
对于M:

前面说过,M>=1且M<2,也就是M可以表示为1.xxxxxxxxxxx的形式,其中xxxxxxxxxxx即为小数部分。、
所以在存储M的时候,只需要存储后面的小数部分就可以了,比如上述的1.011,在存储的时候只存储011。等到读取的时候,只需在前面加上1即可。并且这样做,还可以节省一位有效数字。假如把1保存进去,则小数点后面只能保存22位有效数字,如果不把1保存进去,皆可以保存23位有效数字。

但对于E而言,情况比较复杂:

首先,E是一个无符号整数(unsigned int)
这表示,对于单精度浮点数而言,E的取值范围为0到255;对于双精度浮点数而言,E的取值范围为0到2047
但是,在科学计数法中,E是可以取负数的
IEEE 754规定:存入内存时,E的真实值必须加上一个中间数
对于单精度浮点数,中间数为127
对于双精度浮点数,中间数为1023
列入,2^2在保存时,必须保存为2+127,即10000001

E可以分为三种情况:
E不全为0或不全为1

这种情况是比较常规的,按照上面的规则就可以了
例如 5.5,则其二进制形式为:

0 10000010 01100000000000000000000

E全为0

此时,浮点数的指数E等于1-127(或1-1023)即为真实值
有效数字M不再加上第一位的1,而是还原成0.xxxxxxxx的形式。
此时是一个接近于0的很小的数字

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("n = %d\n", n);
        printf("*pFloat = %f\n", *pFloat);
        return 0;
    }

最后的输出结果为:
这里写图片描述
对于上半部分的,n = 9没有问题,当当以浮点型输出时就变了。
9的二进制为 00000000 00000000 00000000 00001001
当看做为浮点数时 0 00000000 000000000000000000001001
其值为 1.001*2(-146) 是一个特别小的数字,所以输出结果就为0.000000

对于下半部分,
9.0在计算机中的存储为 0 10000010 00100000000000000000000
如果为整数,则为 01000001 00010000 00000000 00000000
则为1091567616,是一个特别大的数字

猜你喜欢

转载自blog.csdn.net/aixiaodeshushu/article/details/81186397
今日推荐