为什么0.4和0.40与BigDecimal不同?

时间:2019-06-28 01:47:11

标签: java junit

我已经读到BigDecimal是用Java表示货币的必经之路。

但是我不明白为什么我的一个单元测试失败并显示以下消息:

org.opentest4j.AssertionFailedError:   
Expected :0.40  
Actual   :0.4

“实际”值是BigDecimal.valueOf(0.398).setScale(2, RoundingMode.HALF_UP)的结果。

所以我想我的问题分为两个部分:

  1. 为什么这些值不相等?
  2. 如何以不会触发这种不匹配的方式将$ 0.40表示为BigDecimal?

1 个答案:

答案 0 :(得分:0)

BigDecimals是数字和“小数位数”的组合。除非两个BD相等,否则它们不认为自己相等。我建议使用.compareTo(other) == 0)来获得答案。

注意:我认为使用BD并不是赚钱的好方法。

通常有两种方法可以计算货币。简单的方法和困难的方法。

最简单的方法是将美分存储在intlong中。因此,将$ 0.40简单地存储为40,而将像$ 12.50这样的内容存储为1250。现在,您有两个问题:您不能代表半美分,并且可能会发生溢出(您不能代表高于2 ^ 31-1美分的金额,但是那是..很多美分。请使其为{{ 1}},我们远远超出了全世界的GDP。

但是,半分钱通常是个问题。遇到这个问题:

我有4美分。我希望将它们分为3个人。

那么,我们该怎么办? BigDecimal无法在这里为您提供帮助;您无法完美地用BD表示4除以3。您必须四舍五入(它是1.33333333 ... BD不能表示无限序列)。即使可以,或者您决定以惊人的数量(让我们说200位数)四舍五入,现在呢?您不能告诉您的银行转帐三分之一。没有简单的答案:如果这是您的应用程序需要执行的操作,那么您需要确定如何处理此问题。例如,“剩余的钱用于房屋”或“软件选择随机的接收者;他们得到2美分,另2个得到1美分。

换句话说,如果“仅使用int / long”不起作用,则BigDecimal的可能性也不大。