c语言中浮点数是如何存储的

        hello大家好,我是c语言boom家宝。这一次的博客内容是浅讲一下在c语言中浮点数是如何存储的。(上一篇博客有讲整数家族的存储,详情请移步主页进行参考)。大家都知道,浮点数有很多种类型,例如float 占用4个字节,double 占用8个字节。这篇博客的内容就围绕这两个类型来讲解。

   根据国际标准IEEE(电气和电子工程协会)规定,任意一个二进制浮点数V都可以表示成(-1)^S *M*2^E的形式。其中(-1)^S表示符号位,即正负。S=0,就是正数。S=1,是负数。(二进制,所以只有0和1)M表示有效数字,大于等于1,小于2。2^E表示指数位。

        这段话是什么意思呢?举个例子,我们要存储的十进制数字是5.0,转换成二进制就是101.0,写成上面的形式就是(-1)^0*1.01*2^2,推出S=0;M=1.01;  E=2;再比如十进制数字是-5.0,转换成二进制就是-101.0,同理可以推出S=1;M=1.01;  E=2;这里博主得指出一点,我们在研究浮点数的存储的时候需要明确知道,有些数字是无法精确存储的,原因就在这里,它会把十进制转化成二进制存储,而小数点后面分别表示2的负1次方,2的负2次方......以此内推,也就是0.5;0.25......等等。故而总会存在某些小数始终都无法取到精确值保存。

        IEEE 754规定:对于32位(float)的浮点数,最高的1位是S;接着的8位是指数E,剩下的23位是有效数字M。如图:

而对于64位(double)来说,最高的1位是S;接着的11位是指数E,剩下的52位是有效数字M。如图:

         IEEE 754 对有效数字M和指数E又有特殊的规定,前面说过,1<=M<2;也就是说,M可以写成1.xxxxxx,其中xxxxxx是小数部分。所以规定,在对M保存的时候,都默认第一位是1,故而不在保存这个1,而是直接对小数部分进行存储,也就是这个xxxxxx部分。最后在使用的时候拿出来再+1。这样就可以节省一个空间,以32位为例,本身留给 M的是23位,把1舍去以后就可以存档24位有效数字了。

        至于指数E,情况就比较复杂。首先,E为一个无符号整数,这意味着E的取值范围是0--255(32位浮点数)和0--2047(64位浮点数)。但是我们知道,科学计数法中的E是可以出现负数的,比如十进制浮点数0.5,二进制就是0.1,在二进制里也就是1*2.0^(-1),E就是-1,是负数。所以就和无符号位的范围相悖,对于这种情况,IEEE754就提出,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127,对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001.这样就不会再有负数的情况了。

猜你喜欢

转载自blog.csdn.net/m0_73321818/article/details/131058332