我原本认为java.math.BigDecimal
应该是用于使用十进制数进行无限精度算术的最佳选择。
请考虑以下代码片段:
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
是解决方案。如果我们甚至无法进行除法运算
,那么这有多有用呢?它实际上提供了一般用途,还是只在非常小众的应用中有用,在那里你幸运地根本不需要除法
?如果这不是正确的答案,那么在金融计算中我们可以使用什么进行精确的除法?(我的意思是,我不是金融专业,但他们仍然使用除法,对吧?)
BigDecimal
而不是double
,我想知道他们如何处理divide
。 - polygenelubricants