V=(-1^S) * M * (2^E)
1.(-1^S)是符号位,当S=1为负,当S=0为正.
2.M有效数字,大于等于1,小于2.
3.2^E表示指数位.
对于32位的浮点数,最高的一位是符号S位,接下来是8位的指数E,接下来的23位为有效数字M.
对于64位的浮点数,最高的一位是符号S位,接下来是11位的指数E,接下来的52位为有效数字M
IEEE 754对有效数字M和指数E,还有一些特别规定.
对于M:
1<=M<2,即M可以写成1.xxxxxxx形式,其中xxxxxx表示小数部分.由于整数部分必为1,规定存储时省略这部分,
比如,保存1.0101时,只保存0101,
等到读取的时候在自动把第一位的1加上.
因此,32位的浮点数可以保存24位有效数字.
对于E:
E是一个无符号整数.这意味着如果E为8位,它的取值范围为0~255;
如果E为11位,它的取值范围为0~2047.
但是,科学计数法中的E是可以出现负数的,所以存入内存的真实值必须再加上一个中间数,
对于8位的E,这个中间数是127;
对11位的E,这个中间数是1023.
比如,2^10的E是10,所以保存成32位的浮点数时,必须保存成10+127=137,即10001001.
指数E可分为以下三种情况:
1.真实值不全为0或1
E-127(或1023),得到真实值
再将有效数字M前加上第一位的1
例如:0.5的二进制为0.1
由于1<=M<2,所以可表示为1.0*2^(-1)
因此E=-1,真实值为-1+127=126,即01111110
M=000 0000 0000 0000 0000 0000
则其二进制存储形式为0 01111110 00000000000000000000000
真实值全为0
指数E等于1-127=126;
有效数字M不再加上1,而是直接使用0.xxxxxxx
这样做是为了表示±0,以及接近于0很小的数字
真实值全为1
此时如果有效数字M全为0,表示±无穷大(有符号位决定正负);
如果有效数字M不全为0,表示不是一个数(NAN)
下面以一道题目来举例
int num = 9;
float *pFloat = (float *)#
printf("num=%d\n",num);
printf("*pFloat=%f\n",*pFloat);
*pFloat = 9.0;
printf("num=%d\n",num);
printf("*pFloat=%f\n",*pFloat);
运行结果:
num=9
*pFloat=0.000000
num=1091567616
*pFloat=9.000000
为什么0X00000009还原成浮点数就成了0.000000?
指数E的真实值等于00000000
因此E=-126
有效数字M=0.000 0000 0000 0000 0000 1001
V=(-1)^0.000 0000 0000 0000 0000 1001*2^(-126)=1.001*2^(-146)
V是一个很小的接近于0的正数
,所以十进制小数表示就是0.000000
浮点数9.0,如何用二进制表示?还原成十进制又是多少?
浮点数9.0等于二进制的1001.0,即1.001*2^3
那么,第一位的符号位s=0,有效数字M等于001后面再加20个0,凑满23位,指数E等于3+127=130,即10000010.
所以写成二进制形式,应该是S+E+M,即
0 10000010 001 0000 0000 0000 0000.还原成10进制即是1091567616.