前言
根据国际标准IEEE(电气和电子工程协会)754规定,C语言中的任何一个浮点数V都可以写成(-1)^S * M * 2^E。
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。M表示有效数字,大于等于1,小于2。2^E表示指数位
所以在C语言中,浮点型数据在内存中储存的是S,E,M,存储顺序也是SEM
一、float类型
1.1float类型在内存中的存储
floatl类型是4个字节,32个比特位,我们规定从左到右,第一个比特位存储S,接下来8个比特位存储E(double是11位),剩下的23个比特位存储M(double是52位)
其中S只用表示该浮点数的正负,
E是用科学计数法表示的浮点数的指数,但是我们又规定E是无符号整数,所以E不能为负数,可我们将0.5用科学计数法表示后,E的值为-1,因此我们又规定保存的是E+127(double是E+1023),127是规定的一个中间值,用来确保E为非负
M是用科学计数法表示的浮点数底数部分,因为规定的M是>=1,<2的,所以我们又规定我们不在保存整数部分的1,而是只保存其小数部分
例如 int a=5.5;
二进制为,101.1,写成IEEE 754规定形式为,(-1)^0 * 1.011 * 2^2,其中,S=0,E=2,M=1.011,但我们在存储时,存储的分别是0,129,011
其中129要写成8位的二进制序列,为10000001
而M占了23个比特位,而表示M只用了3个比特位,所以其余比特位需要在末尾补0
即011 0000000000 0000000000
所以32个比特位依次存储的是S,加了中间值127的E,以及省略了整数部分1的M,其二进制序列为,0100 0000 1011 0000 0000 0000 0000 0000
转化为16进制为40 b0 00 00,让我们来验证一下,代码如下
我们可以看到在调试后,float类型的a在内存中的地址确实和所讲的一致
1.2float类型数据的取出
取出其实是存入的反过程,此时我们是要用得到的SEM的值,用科学计数法的方式表示,但在取出过程中,我们又有了新的规定,
1.当存入的E不全为0或者不全为1时,我们需要给存入的E-127(double为E-1023)得到真实的E,因为我们在存储E的时候,为了保证E非负,给E+127,有效数字M前加上1.,
2.当存入的E全为0时,此时真实的E为-127,我们可以想象一下,一个用科学计数法表示的数字的指数为-127,它是不是无限的向+-0接近,因此规定,E=1-127(或者1-1023),此时有效数字M不再加上1,而是直接还原为0.xxxxx的小数
3.当E全为1时,如果有效数字全为0,表示+-无穷大