写点什么

Java 程序经验小结:避免使用 float 和 double 表示精确数据

发布于: 2021 年 01 月 12 日

1 写在开头


float 和 double 类型主要是为了科学计算和工程计算而设计的。他们执行二进制浮点运算,为了在广泛的数值范围上提供较为精准的快速近似计算而精心设计。

但是,两者都没有提供完全精准的结果,所以不应该用于需要精确结果的场合。

2 使用 float 或者 double 导致的精度丢失


下面我们通过两个例子认识,使用 float 和 double 进行货币计算时,导致的运算精度丢失。

  • 例子一:标准输出运算结果



private static void test3(){ System.out.println(1.03 - 0.43); System.out.println(1.00 - 9 * 0.1); }
复制代码


  • 输出:


0.60000000000000010.09999999999999998
复制代码


例子二:糖果购买。货架上依次有 10 美分、20 美分、30 美分、40 美分等差价格递增的糖果,你手上有 1 美元(1 美元=100 美分),那么你能买多少颗糖果呢?


  • float/double 计算



private static void test4(){ double funds = 1.00; int itemsBought = 0; for (double price = 0.10; funds >= price; price += 0.10){ funds -= price; itemsBought++; } System.out.println(itemsBought + " items bought."); System.out.println("Change:$" + funds); }
复制代码


输出结果:(显然不正确)


3 items bought.Change:$0.3999999999999999
复制代码


bigdecimal 计算


  private static void test5(){    final BigDecimal TEN_CENTS = new BigDecimal("0.1");    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("Change:$" + funds);  }
复制代码


输出结果:



4 items bought.Change:$0.00
复制代码

3 总结

BigDecimal 的源码剖析,可以参考公众号提供的另外一篇文章:《一文带你读懂 BigDecimal 源码


发布于: 2021 年 01 月 12 日阅读数: 19
用户头像

Diligence is the mother of success. 2018.03.28 加入

公众号:后台技术汇 笔者主要从事Java后台开发,喜欢技术交流与分享,保持饥渴,一起进步!

评论

发布
暂无评论
Java 程序经验小结:避免使用float和double表示精确数据