浮点数在内存中的存储
首先先看E的使用,即1E10=1.0*10^10
浮点数包括:float, double, long double
在我们第一次看到这个代码的时候,我们认为结果打印的是9,但是这个程序只有在相同存储类型和打印类型下才会是9,这就充分说明了整型和浮点型在内存中的存储方式不同。上一篇文章我们已经学习了整型的存储方式,那么浮点型的存储方式又是怎么样的呢?
其实浮点型的存储有一个国际标准:IEEE754标准:
即任意一个二进制浮点数V可以表示成以下格式:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0时,V为正数;当s=1时V为负数
M表示有效数字,大于等于1,小于2
2^E表示指数位
运用以上原则,对于一个浮点数9.0化为上述格式:
9的二进制:1001.0
正数,s=0;M=1.001;小数点向右移动3位,E=3
则化为上述形式:(-1)^0 * 1.001 * 2^3
对于参数S,M,E的解释:
S:如果数字为负数则S为1,如果为正数则S为0;
M:M是有效数字,将二进制进行小数点移位,使其大于1小于2得到的
E:小数点移动几位就是几
根据IEEE754标准:对于32位的浮点数,最高位是s,接着的八位是指数E,剩下的23位是有效数字M,如下图:
对于64位的浮点数,最高位是S,接着11位是E,最后52位是M,如下图 :
对于E和M的一些特别规定
M:由于M总是1.xxx,因此在存M的时候,整数部分1不存进去,在拿出来的时候再加上,
如上面的1.001,在存M的时候,只存001,要使用的时候在补1即可
E:首先E是一个无符号整数,这就意味着,如果E是8位的,它的范围是0~255,如果E是11位的它的范围是:0-2047;但是在科学计数法中E可能是负数,那该如何解决这个问题呢?E必须在真实值的基础上加一个中间值,对于8位的是127,11位的是1023;
对于上面的3,在存成32位浮点数E存=3+127;存为64位浮点数E存=3+1023
接下来看对于一个浮点数的存储
先化为二进制,再计算S,M,E 写出对于的二进制位,再化为16进制 ,E要加中间值
从内存中存取浮点数:
1,看首位:是1为符,是0为正
2,取M,记得M取出来的是小数部分,使用的时候补1
3,取E,有以下三种形式
E不全为0或不全为1:
E-中间值(127或1023)得到,真实E即可
E全为0:
在32位上是+127后全为0,在64位上是+1023后全是0;因此E的真实值分别为:
1-127,1-1023
由于此时这个数接近无限小,此时对M的值会有影响,M不再补1,直接是0.xxx
此时化回去有效值不用+1,即+-0.xxx *(1-127),或者+-0.xxx * 2^(1-1023)
E全为1:
E真+127=255,E真为128,此时这个数趋近于正负无穷大。
最后让我们回到一开始,为时候会不按我们设想输出呢?
为什么第二个打印的是0.000000?
首先int 9在内存中存储的是:00000000000000000000000000001001,如果是按照浮点数取出:E为00000000,则由上可知,这个浮点数取出是无穷小,因此是0.000000
为什么3个打印的是1091567616?
首先这个数是按照浮点数存进去的,
9:1001.0
标准形式:(-1)^0 * 1.001 * 2^3
3+127=130,130化为二进制是:10000010
则存在内存中:0 10000010 00100000000000000000000
这是存进去的补码,以整型打印就是1091567616
由上述可以知道,不同的原因是因为整型和浮点型在内存中的存储和取出方式不同。