寻求更好的阅读体验,请移步 :浮点数在计算机中的存储 —【Mculover666的个人博客】。
用于存储小数的数据类型是有单精度浮点型(float)和双精度浮点型(double),那么,浮点数在计算机中是以怎样的二进制代码存储的呢?
本篇将为你揭秘浮点数在计算机中的存储方式~
浮点数在编程时有两种写法:
具体参考常用进制及其转化一文。
IEEE 754
全称ANSI/IEEE Std 754-1985
,是CPU和浮点运算器中广泛使用的二进制浮点算术标准。
IEEE 754标准定义了表示浮点数的格式,一些特殊数值((无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”。
IEEE 754规定了四种表示浮点数值的方式:
IEEE 754标准中规定的二进制浮点数存储格式如图,有三个域分别对应:
所以,二进制浮点数的实际值为:
v a l u e = ( − 1 ) s i g n ∗ f r a c t i o n ∗ 2 e x p o n e n t value = (-1)^{sign} * fraction * 2^{exponent} value=(−1)sign∗fraction∗2exponent
举个例子就懂了:
eg.
十进制小数5.625
转化为二进制为101.101B
,按照IEEE 754标准表示为:1.01101*2^2
,所以得出各个域的值为:
根据这个公式,得出了IEEE 754标准中三个域分别应该存储的数,先理解到这儿即可,后面再详细讲述如何将这三个数进行编码存储。
在IEEE 754标准中,不同的表示方式,对应三个区域的长度也不同。
以常用的单精度和双精度来说:
接下来开始最关键的部分 —— —— 有效值和指数值是以怎样的编码存储的?
IEEE 754中规定了有效值的范围是:大于等于1,小于2。
这意味着有效值的整数部分永远是1,所以这个可以忽略掉(不存储)整数部分的1和小数点,只存储小数部分的值即可。
这样做的好处是节省了一位,比如32位单精度本来只规定了23位用于存储有效数字的值,但实际可以存储24位有效数字的值。
eg.
之前的例子中有效值字段是1.01101B
,省略掉整数部分的1,只存储01101B
,右边不够的补零,所以单精度存储方式中,23位有效值字段的值是0110 1000 0000 0000 0000 000
。
指数E的存储情况比较复杂。
首先,E为一个无符号整数(unsigned int)。这意味着,如果E为8位,它的取值范围为0255;如果E为11位,它的取值范围为02047。但是,科学计数法中的E是可以出现负数的,所以IEEE 754规定,E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。
再用之前的例子来说明了这个知识:
eg.
指数字段是2,在32位单精度存储时,2 + 127 = 129
,所以8位指数字段存储的值是129的二进制,即:1000 0001B
。
最后再讲述一下指数E的三种不同情况所表示的数:
E不全为0或不全为1:浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023)就是实际值,再补上省略掉的1。
E全为0:浮点数的指数E等于1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
E全为1:如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。
综合上述的讲述,示例中十进制小数5.625
用32位单精度存储是:
0 10000001 01101000000000000000000
= 0100 0000 1011 0100 0000 0000 0000 0000
= 0x40b40000
下面在C语言中验证一下结果是否正确:
/**
* @ brief 验证浮点数在计算机中存储的IEEE 754标准
* @ author mculover666
* @ date 2019年6月23日14:49:35
*/
#include
#include
int main(void)
{
float i = 5.625; //0100 0000 1011 0100 0000 0000 0000 0000
int *p = &i;
printf("i = %f\n", i);
printf("i = %x\n", *p);
system("pause");
return 0;
}
/**
* 在Mingw-w64编译器下运行结果:
* ---------------------------------------
i = 5.625000
i = 40b40000
* ---------------------------------------
*/
在64位Win7系统上,用Mingw-w64编译,运行结果如下:
最后附上一个十进制小数转IEEE 754浮点数的小工具:http://www.styb.cn/cms/ieee_754.php。