关于数据精度的一些事
-
基础数据类型
大家都知道,Java中表示小数的基本类型有float, double, 如果你想计算0.3 - 0.1,很遗憾答案并不是0.2,有些人会说,用BigDecimal就可以啦,float和double就是会存在精度问题的。本文想探究一下,为什么, 为什么会无法得到正确答案。
先讲一些题外话,十进制和二进制。
计算机的世界是二进制,0和1组成,
二进制转十进制不在赘述,高中就学过的;
十进制转二进制,看下这个图, 应该也比较清楚了:
主要来看一下,十进制小数怎么转化为二进制(如果是3.45这类的小数拆分为3 和0.45,3按照上面的转换方式,0.45按照如下方式)。
这里,底是2。举例十进制0.1转为二进制:
结果: 0.0
1. 0.1 * 2 = 0.2 整数0为二进制结果的第一位,即0.0;小数0.2作为源,继续执行
2. 0.2 * 2 = 0.4 整数0为二进制结果的第二位,即0.00;小数0.4作为源,继续执行
3. 0.4 * 2 = 0.8 整数0为二进制结果的第三位,即0.000;小数0.8作为源,继续执行
4. 0.8 * 2 = 1.6 整数1为二进制结果的第四位,即0.0001;小数0.6作为源,继续执行
5. 0.6 * 2 = 1.2 整数1为二进制结果的第四位,即0.00011;小数0.2作为源,继续执行
......
最后执行下去,发现0.1转换为二进制为(0.00011001100110011...)2
所以,十进制的0.1计算机无法精确表示。因此,0.3 - 0.1得到的就不是精确值了。不过如果你用0.5 - 0.125是可以得到0.375的,为什么呢?因为,2-1,2-2,2-3这些是可以精确表示的。
当你准备好了,机会来临的时候,你才能抓住