美文网首页
计算机误差之谜

计算机误差之谜

作者: 绝露 | 来源:发表于2017-03-12 20:53 被阅读0次

    问题的由来

    对于这件事情的思考,开始工作上碰到一个问题。
    具体问题如下(简化后):

    public static void main(String[] args) {
            double d0 = 0.2;
            double d1 = d0 + 0.01;
            System.out.println(d1);
    }
    

    本来以为一个很简单的问题。结果计算机却输出了:
    0.21000000000000002
    人家说,进步往往来源于例外。看来,这是我进步的一次机会,哈哈!。

    问题的根源

    先抛出答案:二进制数本身表达能力的局限性。
    为什么会这样? 先来给你演示一下:
    二进制如何表示十进制:


    binary.png
    如二进制的10.101 表示为十进制就是:

    所以,十进制的0.1,用二进制来表示,只能用如下方式:![](http://latex.codecogs.com/png.latex?\inline&space;\frac{1}{16}+\frac{1}{32}+\frac{1}{256}+\frac{1}{512}+\frac{1}{1024}. . .)
    你会发现 . . .之后会有无穷多的数。
    所以在十进制数中很简单的0.1,在二进制数中就是不能精确表达。
    其实这个情况也很好理解,毕竟计数系统是一种符号化语言。而只要是语言就有其缺陷。十进制也有不能精确表达的数,比如无理数,无限循环小数。再如自然语言也有其缺陷之处。中文“鲜”的含义在英文中就找不到一个完美的表达。

    问题的处理办法

    计数系统在表达小数方面都有其缺陷。但是对于整数,都是可以精确表达的。如果我们可以把小数用整数来表示,这个问题不就解决了吗?
    如何用整数来表示小数?
    当你试着用一对一的方式去表达的时候,你会发现这是行不通的。所以我们用两个整数来表达一个小数。如:



    这样的话十进制的0.1,就可被我们用1和-1来表示了。
    这个处理办法在java语言中用BigDecimal实现。

    相关文章

      网友评论

          本文标题:计算机误差之谜

          本文链接:https://www.haomeiwen.com/subject/hhytnttx.html