Java 为什么0.4和0.40与BigDecimal不同?
我已经读到,在Java中表示货币时,BigDecimal是一种方法 但我不明白为什么我的一个单元测试失败了,并显示以下消息:Java 为什么0.4和0.40与BigDecimal不同?,java,junit,Java,Junit,我已经读到,在Java中表示货币时,BigDecimal是一种方法 但我不明白为什么我的一个单元测试失败了,并显示以下消息: org.opentest4j.AssertionFailedError: Expected :0.40 Actual :0.4 “实际”值是BigDecimal.valueOf(0.398).setScale(2,舍入模式。向上舍入)的结果 所以我想我的问题有两个部分: 为什么这些价值观不被平等对待 如何将$0.40表示为一个BigDecimal,而不触发
org.opentest4j.AssertionFailedError:
Expected :0.40
Actual :0.4
“实际”值是BigDecimal.valueOf(0.398).setScale(2,舍入模式。向上舍入)
的结果
所以我想我的问题有两个部分:
大小数是数字和“刻度”的组合。2 BD不认为自己是平等的,除非两者都相等。我建议使用
.compareTo(other)==0)
来获得答案
注:我不认为使用BD是处理货币问题的好方法
通常有两种方法来接近货币。简单的方法和困难的方法
简单的方法是将美分存储在int
或long
中。因此,将$0.40简单地存储为40
,类似$12.50的东西将存储为1250
。你现在有两个问题:你不能代表半美分,可能会发生溢出(你不能代表高于2^31-1美分的金额,但那是…很多美分。让它成为一个长的,我们远远超过了整个世界的GDP)
但是,一般来说,半美分是个问题。以这个问题为例:
我有4美分。我想把这些分给3个人
那么,我们该怎么办?BigDecimal在这里帮不了你;你不能完美地用BD表示4除以3。你必须在某个地方取整(它是1.33333333…BD不能表示无限序列)。即使它可以或者你决定以惊人的数量(比如说200位数字)取整,现在呢?你不能告诉你的银行转帐三分之一美分。没有简单的答案:如果这是你的应用程序需要做的,那么你需要决定如何处理。例如,“剩下的一分钱是给房子的”或“软件随机挑选一个接收者;他们得到2美分,另外2人得到1美分)
换句话说,如果“只使用int/long”不起作用,那么BigDecimal也不好。根据javadocs,将这个BigDecimal与指定的对象进行比较,以确保相等。与compareTo不同,此方法仅当两个BigDecimal对象的值和比例相等时才认为它们相等(因此,使用此方法进行比较时,2.0不等于2.00)。0.40
表示您已测量到第一百位,并且您肯定知道第一百位是0
0.4
表示您尚未测量到第一百位,并且不知道第一百位的值是多少。也可以尝试使用compareTo
No,您应该使用assertEquals(0,actualBigDecimal.compareTo(expectedBigDecimal))代码>3个人分4美分根本没有答案BigDecimal
的行为与这里的银行完全一样。我想使用long
可能会迫使开发人员面对四分问题,比如四分问题,使用BigDecimal
可以让他们在不考虑后果的情况下愉快地分开。措辞恰当的回答。@user207421确实如此,这正是我的观点:使用BD并不是解决所有问题的灵丹妙药。使用BD比使用长的表示美分要复杂得多,我试图告诉OP,这种额外的复杂性通常是不值得的。