浮点数存储方式

在查看内存会发现 int i = 1 在内存中存储的就是 00 00 00 01,而存储 float i=12.5 在内存中的表示 41 48 00 00,查看这个16进制很明显这个浮点数不是通过直接转换得来的,而是通过一些规则的计算规则得来的,这里就引出了 IEEE 规范了,需要了解这个规范的朋友可以去网上查查,我这边就说明下转换方法,我在下面挑了几个特例来进行说明下。

12.5转16进制

计算整数部分

12转换为16进制 0xC 转换成二进制 1100
整数部分等于 1100

计算小数部分

将小数部分进行乘以 2 如果出现整数那么就为 1 没有整数就为 0 一致计算到没有小数为止。
0.5 * 2 = 1.0
通过上面计算,一次计算后小数就为 0 了,所有最终结果就为 1

计算指数

将上计算出来整数部分 1100 跟小数部分 1 进行拼接得到 1100.1,得到拼接结果进行计算指数指数是通过左移或者右移小数点得到的,具体多久左移多久右移请观察下面的表格。

数据 移动方式 指数 最终结果
1100.1 左移 3 1.1001
10001000.101 左移 7 1.0001000101
0.00101 右移 -3 1.01

观察上面表格数据我们可以总结出,是左移还是右移是先看小数点左边是否存在 1 ,存在就进行左移,不存在就进行右移,具体移动多少位,是由移动到小数点左边只有一个 1 为止,移动的位数就是 指数 ,向左边移动 指数 就为正数,向右边移动 指数 就为负数。
通过上面的规则得到的指数为 3 ,计算指数后的结果为 1.1001

计算

计算完指数得到的结果 1.1001,指数为 3

浮点数占用 32 位,第1位是符号位,2 ~ 9位是整数位,10 ~ 32位为小数位,下面红色表示符号位、蓝色表示整数位、紫色表示小数位。
0 0000 0000 0000 0000 0000 0000 0000 000

符号位计算

正数符号位 0,负数符号位为 1
结果
0 0000 0000 0000 0000 0000 0000 0000 000

小数计算

直接将计算完指数的结果中的小数部分填写进小数部分。
上面计算得到的小数部分就是 1001
结果
0 0000 0000 1001 0000 0000 0000 0000 000

整数计算

将计算 指数 + 127 得到的数转为16进制,写入到整数部分。
127 + 3 = 130转为16进制0x82得到二进制数据 1000 0010
结果
0 1000 0010 1001 0000 0000 0000 0000 000

最终结果

二进制形式
0100 0001 0100 1000 0000 0000 0000 0000
16进制形式
0x41480000

17.4转16进制

下面转换我这边会提跟 12.5 转换的差异,很多转化和转换 12.5 一样的,就不细写了。

计算整数部分

17 转为16进制得到 11,二进进制表现形式 0001 0001

计算小数部分

0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0

通过上面可以发现该小数部分,按照规则计算出现了循环,所以浮点数需要指定精度,我们这边就保存8位就可以了,那结果就为 0110 0110

计算指数

0001 0001 + 0110 0110 = 0001 0001.0110 0110
通过观察拼接结果,需要左移 4 位,最终得到数据 1.000101100110,指数 4

计算

计算完指数得到的结果 1.000101100110,指数为 4

符号位计算

0 0000 0000 0000 0000 0000 0000 0000 000

小数计算

0 0000 0000 0001 0110 0110 0000 0000 000

整数计算

127 + 4 = 131,转为16进制 0x83 ,二进制体现形式 1000 0011
0 1000 0011 0001 0110 0110 0000 0000 000

最终结果

二进制形式
0100 0001 1000 1011 0011 0000 0000 0000
16进制形式
0x418b3000
第三方转换结果
image
第三转换结果是 418B3333 和我们计算出的结果存在差异,是因为我们在计算小数部分的只计算了 8 位,因为对 0.4 进行计算的时候,它的小数位计算是无限循环的。

-0.6转16进制

计算整数部分

整数为 0 那结果就为0。

计算小数部分

0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1
0.6 * 2 = 1.2 -> 1
0.2 * 2 = 0.4 -> 0
0.4 * 2 = 0.8 -> 0
0.8 * 2 = 1.6 -> 1

又出现了循环,我这边就保留 8 位了,那结果等于 1001 1001

计算指数

0 + 10011001 = 0.10011001
这里可以发现上面的数据左右没有 1 了,那就需要进行右了,最终移动完后数据 1.0011001 ,指数为 -1。

计算

计算完指数得到的结果 1.0011001,指数为 -1

符号位计算

1 0000 0000 0000 0000 0000 0000 0000 000
由于当前数据是负数,那符号位就是 1 。

小数计算

1 0000 0000 0011 0010 0000 0000 0000 000

整数计算

127 + (-1) = 126,转为16进制 0x7E ,二进制体现形式 0111 1110
1 0111 1110 0011 0010 0000 0000 0000 000

最终结果

二进制形式
1011 1111 0001 1001 0000 0000 0000 0000
16进制形式
0xbf190000

总结

通过上面的几个例子,计算浮点数的步骤可以分为一下几步:
拆分浮点数: 将浮点数拆分为符号部分、整数部分、小数部分。
转换整数部分: 将整数部分转化成二进制,为计算提供准备。
转换小数部分: 按照转换规则转换,将小数部分转换为二进制,为计算提供准备。
指数计算: 这一步特别重要,但是只需要记住左边有 1 就是左移,移动到左边只有一个 1 为只,移动的位数就是指数,并且左移指数为正数,右移指数为负数
小数计算: 直接将小数部分放入小数的位数上。
正数计算: 127 + 指数,就是整数数据。
符号位计算: 正数为 0 ,负数为 1 。

posted @ 2022-08-12 18:00  可爱小A  阅读(418)  评论(0编辑  收藏  举报