zoukankan      html  css  js  c++  java
  • Java中的二进制运算出错问题

    问题:

    最近在做Java web项目中需要计算金额总和,在这里出现了一个问题是我以前没有关注到的:

    System.out.println(2.0-1.1);

    执行时候的console中打印输出的是

    0.8999999999999999

    而不是正常计算出2.0-1.1=0.9这个答案,

    原因:

    对此我找了一些解答,主要是二进制机器在处理十分之一(0.1)上出现的问题。

    主要问题出在小数的二进制表示上

    这里参考了这篇博客所讲的:http://hxraid.iteye.com/blog/504293

    (1)  十进制整数如何转化为二进制数

               算法很简单。举个例子,11表示成二进制数:

                         11/2=5   余   1

                           5/2=2   余   1

                           2/2=1   余   0

                           1/2=0   余   1

                              0结束         11二进制表示为(从下往上):1011

              这里提一点:只要遇到除以后的结果为0了就结束了,所有的整数除以2是不是一定能够最终得到0。换句话说,所有的整数转变为二进制数的算法会不会无限循环下去呢?绝对不会,整数永远可以用二进制精确表示 ,但小数就不一定了。

     (2) 十进制小数如何转化为二进制数

               算法是乘以2直到没有了小数为止。举个例子,0.9表示成二进制数

                         0.9*2=1.8   取整数部分  1

                         0.8(1.8的小数部分)*2=1.6    取整数部分  1

                         0.6*2=1.2   取整数部分  1

                         0.2*2=0.4   取整数部分  0

                         0.4*2=0.8   取整数部分  0

                         0.8*2=1.6   取整数部分  1

                         0.6*2=1.2   取整数部分  0

                                  .........      0.9二进制表示为(从上往下): 1100100100100......

               注意:上面的计算过程循环了,也就是说*2永远不可能消灭小数部分,这样算法将无限下去。很显然,小数的二进制表示有时是不可能精确的 。其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10。

    这也就解释了这个问题出现的原因。

    解决:

    知道原因之后我们应该怎么做呢?其实可以用Java中提供的

    BigDecimal实现精确加减乘除运算

    BigDecimal提供的BigDecimal(String val)构造方法,使用BigDecimal要用String来够造,要做一个加法运算,需要先将两个浮点数转为String,然后够造成BigDecimal,在其中一个上调用add方法,传入另一个作为参数,然后把运算的结果(BigDecimal)再转换为浮点数。

    加减乘除操作:

    public BigDecimal add(BigDecimal value);
    public BigDecimal subtract(BigDecimal value);
    public BigDecimal multiply(BigDecimal value);
    public BigDecimal divide(BigDecimal value);

    在计算完之后,利用doubleValue()方法将BigDecimal转换成Double类型就可以避免上述的错误了。

  • 相关阅读:
    Spring Cloud Hystrix Dashboard的使用 5.1.3
    Spring Cloud Hystrix 服务容错保护 5.1
    Spring Cloud Ribbon 客户端负载均衡 4.3
    Spring Cloud 如何实现服务间的调用 4.2.3
    hadoop3.1集成yarn ha
    hadoop3.1 hdfs的api使用
    hadoop3.1 ha高可用部署
    hadoop3.1 分布式集群部署
    hadoop3.1伪分布式部署
    KVM(八)使用 libvirt 迁移 QEMU/KVM 虚机和 Nova 虚机
  • 原文地址:https://www.cnblogs.com/winterfells/p/8595595.html
Copyright © 2011-2022 走看看