Skip to content

Java 解惑 -02:找零时刻

🏷️ 《Java 解惑》

java
System.out.println(2.00 - 1.10); // print 0.8999999999999999

这个问题和 这篇博客 中描述的 0.30000000000000004 问题都来自于同样的原因:二进制无法准确地表示大部分小数。

java
System.out.println(0.1 + 0.2); // 0.30000000000000004

虽然可以通过如下格式化的方式,调整打印的结果以显示正确的值,但其储存的值仍然是错误的。

java
System.out.printf("%.2f%n", 2.00 - 1.10); // print 0.90

解决这种金额相关的计算,最好的办法是降低计算的单位,采用整形来计算。比如人民币可以采用分,甚至是厘来计算,将浮点运算转换为整形计算。

java
System.out.println((200 - 110) + "cents"); // print 90cents

如果必须使用小数,则应该使用 BigDecimal 类型。不过在 Java 中没有对 BigDecimal 型做运算符的重载,导致使用起来不是很方便。
另外一个必须要注意的是使用 String 型来实例化 BigDecimal ,否则由于入参的不精确进而导致 BigDecimal 的实例也不精确。

java
System.out.println(new BigDecimal(2.00).subtract(new BigDecimal(1.10))); // print 0.899999999999999911182158029987476766109466552734375

System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10"))); // print 0.90