float计算的底层原理
第一步: 浮点数转换为二进制表示
整数部分直接转换成二进制,小数部分让小数一直乘2,小于1则用结果继续乘,大于1则结果减1继续乘,等于1则结束。
比如8.8 整数部分转换成1000,小数部分
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
0.4 * 2 = 0.8 —————0
.
.
.
小数部分就是110011001100……
第二步: 将得到的二进制小数转换为科学计数法
8.8 的二进制小数表示为: 1000.110011001100…
转换为科学计数法就是 1.000110011001100… * 2 ** 3
第三步: 存储:
- Float32,用32位的二进制来存储一个浮点数。
- Float64,用64位的二进制来存储一个浮点数。
如图可知:
- sign 表示正负 0正1负
- 8位 exponent 存储范围 -126-127 如8.8 指数为3,计算时将3+127转换为二进制储存在这里,小数整数部分为0的话则是num*2 ^(-n)
- 23 位的fraction存储存放科学计数法的小数部分
- 最终,8.8 在内存中存储的二进制为 0 1000 0010 00011001100110011001100
总结:
通过对浮点型的存储原理的学习,了解到浮点型其实是一种非精确的表达小数的方式,因为他的fraction中有位数限制,超过就会忽略。
float64和float32类似,只是用于表示各部分的位数不同而已,其中:sign=1位
、exponent=11位
、fraction=52位
,也就意味着可以表示的范围更大了。
ps:在开发中想精确的处理小数时,可以使用decimal。比如在我做过的一个小项目中涉及数据库存储金额操作小数为了精确就用decimal ,他的缺点是占内存空间,在内存中是以类似字符串的形式存储的所以更占内存~