第48条:如果需要精确的答案,请避免使用float和double

        float和double主要为了科学计算和工程计算而设计,执行二进制浮点运算,这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不适合用于需要精确结果的场合,尤其是货币计算。

//假设有1.03元,花掉0.42元后

System.out.println(1.03 - .42);//0.6100000000000001

System.out.println(1.00 - 9 * .10);//0.09999999999999998

使用舍入可以解决上面问题,但并不是所有的问题都能用舍入解决,如有1元,有0.1,0.2,0.3,一直到1元的糖果,从0.1开始买,直到不能支付为止:

public static void main(String[] args) {

    double funds = 1.00;

    int itemsBought = 0;

    for(double price = .10; funds >= price; price += .10) {

          funds -= price;

          itemsBought++;

     }

     System.out.println(itemsBought + " items bought.");

      System.out.println("Money left over: $" + funds);
}

结果是:

3 items bought.

Money left over: $0.3999999999999999

使用BigDecimal是正确的办法

public static void main(String[] args) {

     final BigDecimal TEN_CENTS = new BigDecimal(".10");

     int itemsBought = 0;

     BigDecimal funds = new BigDecimal("1.00");

     for(BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) {

          itemsBought++;

          funds = funds.subtract(price);

     }

     System.out.println(itemsBought + " items bought.");

     System.out.println("Money left over: $" + funds);

}

结果是:

4 items bought.

Money left over: $0.00


使用BigDecimal的缺点是:1.与基本类型相比,不方便(需要创建BigDecimal对象);2.速度慢

使用int或者long,取决于涉及的数值大小,同时要自己处理十进制小数,以分为单位,而不是以元为单位计算,就可以使用int来处理:

public static void main(String[] args) {

     int itemsBought = 0;

     int funds = 100;

     for(int price = 10; funds >= price; price += 10) {

          itemsBought++;

          funds -= price;

      }

     System.out.println(itemsBought + " items bought.");

     System.out.println("Money left over: $" + funds);
}

结果与用BigDecimal是一样的。

总结:对于需要精确答案的计算,不能使用float或者double,BigDecimal允许完全控制舍入,如果业务要求涉及多种舍入方式,使用BigDecimal很方便,如果性能很关键,涉及的数值不大,就可以使用int或者long,如果数值范围没有超过9位十进制数字,可以使用int,如果不超过18位数字,使用long,如果数值可能超过18位,就必须用BigDecimal。



最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java经典问题算法大全 /*【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子...
    赵宇_阿特奇阅读 1,924评论 0 2
  • 《Effective Java》这本书介绍了Java编程中78条极具使用价值的经验规划,包括创建和销毁对象,类和接...
    nanteschen阅读 792评论 0 5
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,785评论 18 399
  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,998评论 0 23
  • 摘下一片银杏叶,想做成书签。 夹在日记里,夹在你我回忆的那一页。 那页记录了我们一起去过的银杏林,一起看过的风景。...
    芝麻小圆子阅读 347评论 0 0