用于金融计算和非终止计算的BigDecimal

4
我相信这个问题的答案很简单,但我无法决定必须做什么。所以这就是问题:假设我们遵循使用 BigDecimal 进行财务计算的"最佳实践",如何处理会抛出异常的计算?
例如:假设我必须将"用户金额"分配给投资于"n"个不同实体。现在考虑用户提交100美元用于投资,并分为3个债券的情况。等效的代码如下:
public static void main(String[] args) throws Exception {
    BigDecimal bd1 = new BigDecimal("100.0");
    BigDecimal bd2 = new BigDecimal("3");
    System.out.println(bd1.divide(bd2));
}

但是我们都知道,这段代码会抛出一个 ArithmeticException 异常,因为除法是非终止的。当使用无限精度数据类型进行计算时,如何处理这种情况呢?

谢谢,
sasuke

更新:鉴于 RoundingMode 可以帮助解决此问题,下一个问题是,为什么100.0/3不是33.33而是33.3? 33.33 不应该是“更”准确的答案吗?你期望得到33美分而不是30美分。是否有任何方法可以调整这个结果?


除法方法还有重载实现,可以指定舍入模式,请参见此链接 - Rajeev Sreedharan
@sasuke,在你的更新中:我已经测试了bd1.divide(bd2, 2, RoundingMode.HALF_EVEN)如下所示),结果为33.33。 - krock
3个回答

7
答案是使用其中一个BigDecimal.divide()方法,该方法指定了一个RoundingMode
例如,以下代码使用舍入模式half even或银行家舍入(但根据要求可能更适合半向上或其他舍入模式),并将四舍五入到小数点后2位:
bd1.divide(bd2, 2, RoundingMode.HALF_EVEN);

谢谢提供链接;现在的问题是,为什么 100.0/3 不是 33.33 而是 33.333.33 不是更准确的答案吗?我有没有办法调整这个结果? - sasuke
@sasuke,对于33.33,请将比例设置为2,就像上面的例子一样。这完全取决于您想要舍入到多少位小数。如果省略比例参数,它将使用bd1的比例,即1(100.0有一个小数位)。 - krock
谢谢,我完全忽略了那一部分。目前为止,我的所有问题都得到了解答。 :-) - sasuke

2

divide有一个重载方法可以选择舍入模式,你需要选择一个。我认为“银行家舍入法”是货币计算中最常用的一种。


+1;但这仍然无法解释100/3 = 33.3比100/3 = 33.33更合理,因为33分比30分更接近答案。 - sasuke

1
bd1.divide(bd2, 5, BigDecimal.ROUND_FLOOR)

这只是一个例子,取决于您想要的舍入方式。


我没有点踩,但你发的参考资料质量很差,而且来源不可靠。 - Rajeev Sreedharan
好的,它并不完全是一个“参考资料”,更像是一个代码示例。但是好的,我明白了,我已经删除了链接。 - Guillaume

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接