乐趣区

关于java:JAVA中的浮点数与二进制

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


对于二进制的底层,还有很多问题,有待咱们摸索

多理解一点,就少一些困惑

退出移动版