浮点数陷阱—无法精确保存0.1 ?

浮点数陷阱

  • 陷阱:浮点数遵循IEEE754标准,无法精确保存0.1
    • 问题
    • 结论
    • 解析
    • 结语


陷阱:浮点数遵循IEEE754标准,无法精确保存0.1


问题

  • 看三行简单却诡异的代码,观察运行结果
       	double x = 1.0 / 10;
        double y = 1 - 0.9;
        double z = 0.1+0.2;
        
        // 观察x、y、z的结果
        
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);

浮点数陷阱—无法精确保存0.1 ?_第1张图片

  • 为什么1 - 0.9 != 0.1 ?
  • 为什么0.1+0.2 != 0.3 ?

结论

  在计算机中,浮点数虽然表示的范围大,但是浮点数有个非常重要的特点——浮点数常常无法精确表示。

  例如,浮点数0.1在计算机中就无法精确表示,所以运算结果就会出现偏差。


解析

  如果你了解浮点数二进制存储机制,那么就很简单,二进制只能精确存储小数域是2的负指数幂及其线性组合的数。例如0.25、0.5…

  如果你不了解,那么一起来看…

    0.1 = 1/24 + 1/25 + 1/28 +1/29+1/212+1/213

    0.110=0.0001100110011001100110011…2

  这是一个二进制无限循环小数。

计算机内存有限,我们不能储存所有的小数位数,所以在某个精度点直接舍弃,单精度精确到23位,双精度精确到52位。

  也就是说,0.1在计算机内部根本就不是精确的0.1,而是一个有舍入误差的0.1。当代码被编译或解释后,0.1已经被四舍五入成一个与之很接近的计算机内部数字,导致计算还没开始,一个很小的舍入错误就已经产生了。这也就是上面问题产生的根本原因。

关于浮点数的存储机制请移步——浮点数揭秘——IEEE754


结语

  不同行业,要求的精度不是线性的,我们允许(对结果无关紧要的)误差存在,例如10.0001与10.001在铁路工程师看来都是合格的。
  虽然允许误差存在,但是程序员在使用浮点数进行计算或逻辑处理时,稍不注意,就可能会问题。
  记住,最好完全避免使用浮点数进行比较!

  在银行业务中用Java中的BigDecimal数学工具类来表示钱数。


水平有限,如有错误之处,还请指正。

你可能感兴趣的:(数据类型)