JAVA 中的浮点数与二进制
先来看一段简略的代码
public static void main(String[] args) {System.out.println(0.1+0.2);
}
打印后果如下:
0.30000000000000004 // 为什么 0.1+0.2 不等于 0.3?
为什么会呈现这种诡异的答案呢?
这还得从浮点数的二进制示意办法说起
这年头儿,连过马路的老奶奶预计都晓得,计算机是采纳二进制计数的
来,简略的考你一下:请把数字 15 写成二进制的模式
// 答案应该比较简单 0000 1111
置信你对整数的二进制曾经比拟相熟
但如果我换成小数呢?3.14159265359该怎么示意?
其实,如果不搞底层设计,个别人还真的不太晓得这个答案
但你只有了解小数在二进制中是如何示意的
才可能明确文章结尾的案例【为什么 0.1+0.2 不等于 0.3?】
咱们以小数 0.1 为例,看看它是如何应用二进制存储的
第一步,把 0.1 乘以 2,失去的后果 0.2,整数局部 0 取走
第二步,把上一步留下的小数局部 0.2,乘以 2,失去的后果 0.4,整数局部 0 取走
第三步,把上一步留下的小数局部 0.4,乘以 2,失去的后果 0.8,整数局部 0 取走
第四步,把上一步留下的小数局部 0.8,乘以 2,失去的后果 1.6,整数局部 1 取走...... 直到,小数局部为 0
下图展现了计算的过程 ↓
最终的二进制,就是整数局部的合集
写进去大略是这样:
0001 1001 1001 1001 1001 ...
能够看到,1001 的局部,是有限循环的
咱们用二进制的小数把它写进去大略是这样
0.0001 1001 1001 1001 1001 ...
它相当于
你会发现,它并不等于 0.1
它只是一个近似值
所以,二进制保留的位数越多,精度也就越高
晚期的计算机其实是不能解决浮点数的
直到 IEEE 754 规范呈现后,计算机能力解决浮点数
依据 IEEE 754 规范,float 类型,共 4 个字节,32 个 bit 位
其中 指数局部 占 8 位,小数局部 占 23 位
那么 指数局部 和 小数局部 别离用来保留什么呢?
咱们仍然以 数字 0.1 为例,咱们方才曾经失去了它的二进制
0.0001 1001 1001 1001 1001 ...
依照 IEEE 754 规范,咱们须要把它的小数点,向右挪动
直到整数局部是 1 为止
0.0001 1001 1001 1001 1001 ...
// 小数点向右挪动 4 位
// 相当于乘以 2 的 4 次方
0001.1001 1001 1001 1001 ...
// 也就是
1.1001 1001 1001 1001 ...
// 为了维持数字大小不变
// 再乘以 2 的 - 4 次方
最终变成
float 小数局部只能保留 23 位
-4 就是 指数局部
1001…… 就是 小数局部
小数点的地位不是固定的,而是浮动的,故名:浮点数
理解到这一点,你就可能承受更多看起来奇怪而乏味的景象
比方
float f1=0.4f;double d1=0.4;System.out.println(f1==d1);//falseSystem.out.println(f1>d1); //true
f1 还原为 10 进制,后果为 0.40000000596046450000
d1 还原为 10 进制,后果为 0.40000000000000000000
对于二进制的底层,还有很多问题,有待咱们摸索
多理解一点,就少一些困惑