浮点数在计算机中的存储

用于存储小数的数据类型是有单精度浮点型(float)和双精度浮点型(double),那么,浮点数在计算机中是以怎样的二进制代码存储的呢?

本篇将为你揭秘浮点数在计算机中的存储方式~

一、浮点数在编程时的表示方式(书写方式)

浮点数在编程时有两种写法:

  • 传统写法:直接写(eg. 0.1234)
  • 科学计数法:用e表示(eg. 12.34e-2)

二、十进制小数与二进制浮点数之间的转化

  • 十进制小数 -> 二进制浮点数
  • 二进制浮点数 -> 十进制小数

具体参考常用进制及其转化一文。

三、浮点数按照IEEE 754标准存储在计算机中

IEEE 754

IEEE 754全称ANSI/IEEE Std 754-1985,是CPU和浮点运算器中广泛使用的二进制浮点算术标准

IEEE 754标准定义了表示浮点数的格式,一些特殊数值((无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”。

IEEE 754规定了四种表示浮点数值的方式:

  • 单精确度(32位)
  • 双精确度(64位)
  • 延伸单精确度(43比特以上,很少使用)
  • 延伸双精确度(79比特以上,通常以80位实现)

IEEE 754中二进制浮点数的存储格式

IEEE 754标准中规定的二进制浮点数存储格式如图,有三个域分别对应:

  • sign:最高位是符号位,0表示正数,1表示负数(对应二进制小数的符号)
  • exponent:指数值的编码值(对应二进制小数的指数)
  • fraction:有效值的编码值(对应二进制小数的有效值,范围:大于等于1,小于2

所以,二进制浮点数的实际值为:

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)signfraction2exponent

举个例子就懂了:

eg.

十进制小数5.625转化为二进制为101.101B,按照IEEE 754标准表示为:1.01101*2^2,所以得出各个域的值为:

  • sign:0
  • exponent:2
  • fraction:1.01101

根据这个公式,得出了IEEE 754标准中三个域分别应该存储的数,先理解到这儿即可,后面再详细讲述如何将这三个数进行编码存储。

IEEE 754中每个域的长度

在IEEE 754标准中,不同的表示方式,对应三个区域的长度也不同。

以常用的单精度和双精度来说:

  • 32位单精度

浮点数在计算机中的存储_第1张图片

  • 64位双精度

浮点数在计算机中的存储_第2张图片

接下来开始最关键的部分 —— —— 有效值和指数值是以怎样的编码存储的?

IEEE 754存储格式的有效值段(fraction)

IEEE 754中规定了有效值的范围是:大于等于1,小于2

这意味着有效值的整数部分永远是1,所以这个可以忽略掉(不存储)整数部分的1和小数点,只存储小数部分的值即可。

这样做的好处是节省了一位,比如32位单精度本来只规定了23位用于存储有效数字的值,但实际可以存储24位有效数字的值。

eg.

之前的例子中有效值字段是1.01101B,省略掉整数部分的1,只存储01101B,右边不够的补零,所以单精度存储方式中,23位有效值字段的值是0110 1000 0000 0000 0000 000

IEEE 754存储格式的指数段(exponent)

指数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)。

四、C语言程序验证示例结果

综合上述的讲述,示例中十进制小数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

你可能感兴趣的:(C语言集锦,IEEE754)