【发布时间】:2011-02-14 12:23:40
【问题描述】:
我认为java.math.BigDecimal 应该是对十进制数执行无限精度算术需求的 The Answer™。
考虑以下 sn-p:
import java.math.BigDecimal;
//...
final BigDecimal one = BigDecimal.ONE;
final BigDecimal three = BigDecimal.valueOf(3);
final BigDecimal third = one.divide(three);
assert third.multiply(three).equals(one); // this should pass, right?
我预计 assert 会通过,但实际上执行甚至没有到达那里:one.divide(three) 导致 ArithmeticException 被抛出!
Exception in thread "main" java.lang.ArithmeticException:
Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide
事实证明,API 中明确记录了这种行为:
在
divide的情况下,精确商可以有无限长的十进制扩展;例如,1 除以 3。如果商具有非终止十进制扩展并且指定运算返回精确结果,则抛出ArithmeticException。否则,将返回除法的确切结果,就像其他操作一样。
进一步浏览API,发现实际上divide有各种重载执行不精确除法,即:
final BigDecimal third = one.divide(three, 33, RoundingMode.DOWN);
System.out.println(three.multiply(third));
// prints "0.999999999999999999999999999999999"
当然,现在明显的问题是“有什么意义???”。我认为BigDecimal 是我们需要 exact 算术时的解决方案,例如用于财务计算。如果我们甚至不能准确地divide,那么这有多大用处?它实际上是用于通用目的,还是仅在非常小众的应用程序中有用,幸运的是,您根本不需要divide?
如果这不是正确的答案,我们在财务计算中使用什么可以进行精确除法? (我的意思是,我没有金融专业,但他们仍然使用除法,对吗???)。
【问题讨论】:
-
顺便说一句,我非常感谢那些使用过财务软件的人的见解。我经常听到
BigDecimal被double提倡,我想听听他们如何处理divide。 -
我正在开发一个非常复杂的 Java 应用程序,在 JTables 中显示大量财务信息(顺便说一句,JTables 如此复杂且经常更新,以至于我不得不使用几个 java.sun.com/products/jfc/tsc/articles/ChristmasTree 优化来获得我的 JTables 在快速机器上的表现可以接受)。 突出的两件事:单位通常是美分,我有自己的 NumDiv 理性抽象。请注意,这不是 Java 平台的缺点:最坏的情况是默认 JAVA API 的缺点(如果有的话)。
标签: java precision division bigdecimal financial