浮点数是我们在程序里常用的数据类型,它在内存中到底是怎么样的形式存在。

现代计算机中,一般都以IEEE 754标准存储浮点数,这个标准的在内存中存储的形式为:

C语言中浮点数的二进制表示,以及内存形式-Alkaid

对于不同长度的浮点数,阶码与小数位分配的数量不一样,如下:

C语言中浮点数的二进制表示,以及内存形式-Alkaid

对于32位的单精度浮点数,数符分配是1位,阶码分配了8位,尾数分配了是23位。

根据这个标准,我们来尝试把一个十进制的浮点数转换为IEEE754标准表示。

例如:178.125

首先是乘2取整法,即每一步将十进制小数部分乘以2,所得积的小数点左边的数字(0或1)作为二进制表示法中的数字,直到满足你的精确度为止。

转换过程:

0.874的转换过程(取精度为6位):

0.874*2=1.748 小数点左边为 1
0.748*2=1.496 小数点左边为 1
0.496*2=0.992 小数点左边为 0
0.992*2=1.984 小数点左边为 1
0.984*2=1.968 小数点左边为 1
0.968*2=1.936 小数点左边为 1

十进制:123.874

二进制:1111011.110111

 

一.先把浮点数分别把整数部分和小数部分转换成2进制

  1. 整数部分用除2取余的方法,求得:10110010
  2. 小数部分用乘2取整的方法,求得:001
  3. 合起来即是:10110010.001
  4. 转换成二进制的浮点数,即把小数点移动到整数位只有1,即为:1.0110010001 * 2^111,111是二进制,由于左移了7位,所以是111

 

二. 把浮点数转换二进制后,这里基本已经可以得出对应3部分的值了

  1. 数符:由于浮点数是正数,故为0.(负数为1)
  2. 阶码 : 阶码是需要作移码运算,在转换出来的二进制数里,阶数是111(十进制为7),对于单精度的浮点数,偏移值为01111111(127)[偏移量的计算是:2^(e-1)-1, e为阶码的位数,即为8,因此偏移值是127],即:111+01111111 = 10000110
  3. 尾数:小数点后面的数,即0110010001
  4. 最终根据位置填到对位的位置上:C语言中浮点数的二进制表示,以及内存形式-Alkaid

C语言中浮点数的二进制表示,以及内存形式-Alkaid

可能有个疑问:小数点前面的1去哪里了?由于尾数部分是规格化表示的,最高位总是“1”,所以这是直接隐藏掉,同时也节省了1个位出来存储小数,提高精度。

 

例题:为什么以下代码运行结果为0:

浮点数作为变参函数的参数时需要转换为双精度浮点值

float作为变参函数的参数需要转换为双精度浮点值(重要的话重复3遍)。

知道了这些,就不难理解本文开头的程序输出为0了, float (15) 转成双精度浮点数后,高位4字节为0,且此高4位和%d对应,故输出为0