开课吧孤尽T31训练营学习笔记-DAY18-浮点数全解析

191 阅读3分钟

浮点数的奥秘

经过烧脑的课程,琢磨了好久,终于明白了浮点数是怎么存储的。

一、先认识一下浮点数

1.1 存储格式

以单精度浮点数float为例,存储规则为。

image.png

1.2 实例查看

我们看一下16.9这个数字存储是什么样的二进制,可以使用以下代码:

Float f1 = 19.9f;
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f1)));

得到结果:

1000001100111110011001100110011

看到只有31位,其实第一位的符号位为0,没有打印出来,其实是

01000001100111110011001100110011

根据存储格式我们得知指数位为100000110,而有效数字为0111110011001100110011。 这几个数字怎么得来的,我们详细分析一下。

二、浮点数存储规则

这一节首先给出浮点数存储的实际规则,并从正反两个方面解析。

2.1 浮点数规则

有效数字

跟根据1.1中的存储格式,23位有效数字位存储的是小数部分,整数部分肯定是个1。这样相当于根据约定,可以多一位的精度。

指数位

指数位采用移码处理后存储无符号位的整数,我们列个表来说明。 约束八个0和八个1不能用。

动作最小值最大值
原始补码表示-128127
移1280255
移128去掉八0八最终表达范围-127126
移127-1254
移127去掉八0八最终表达范围-126127

移动127后,八个1是 原来的(-128)10000000 + 01111111 = 11111111; 0 是 原来的(-127)10000001 + 01111111 = 00000000; 这样相当于去掉了两个最低位,可以保证数据表达的上限。

规则分析完了,真是感叹设计者利用规则来榨取32bit存储数据的极限能力。

2.2 反向分析

我们反向分析,看从二进制怎么推导出10进制数。

浮点数19.9f表示为:01000001100111110011001100110011

第一位符号位为0, 正数。

指数位是:10000011(131), 反向移码相当于131-127=4,也就是指数位是4

有效数字,加上省略存储的1,那就是1.00111110011001100110011。

有效数字往左移动指数位数4,就是10011.1110011001100110011,可以看到整数位10011,就是19, 小数位0.5+0.25+0.125 (0.0625)(0.03125) + 0.015625 = 0.890625 后面再续上,基本接近于0.9了。

2.3 正向分析

正向分析,我们看怎么从10进制数推导出二进制数。

19.9f, 首先整数位置变换为10011;小数位采用乘2取整法。

数据乘2结果取整
0.91.81
0.81.61
0.61.21
0.20.40
0.40.80
0.81.61
0.61.21
0.20.40
0.40.80

那么就得出整个二进制数字位是10011.111001100。

首位变成1,需要移位4,那么指数位就是4,移码加上127就是131;那么指数位就是

10000011

数字变成1.0011111001100,省略首位存储,那么有效数字就是

0011111001100

三、0的表示

这个是我的假设:

表示0时,符号位是八个0,此时不再计算有效数字省略的1.

学习浮点数的感悟

  1. bit使用设计上榨取存储能力,

  2. 巧妙的设计,提高计算机计算的效率。