为什么BigDecimal(“5.50”)不等于BigDecimal(“5.5”)以及如何解决这个问题?

时间:2010-10-05 18:19:52

标签: java equals bigdecimal

实际上,我找到了可能的解决方案

//returns true
new BigDecimal("5.50").doubleValue() == new BigDecimal("5.5").doubleValue()

当然,可以通过类似Math.abs (v1 - v2) < EPS的方式对其进行改进,以使比较更加稳健,但问题是这种技术是否可以接受或是否有更好的解决方案?

如果有人知道为什么java设计师决定以这种方式实现BigDecimal的平等,那么阅读会很有趣。

3 个答案:

答案 0 :(得分:79)

来自BigDecimal的javadoc

  

<强>等于

     

public boolean equals(Object x)

     

将此BigDecimal与指定的Object进行比较以获得相等性。与compareTo不同,此方法仅考虑两个BigDecimal个对象,只要它们的值和比例相等(因此通过此方法比较时2.0不等于2.00)。 / p>

只需使用compareTo() == 0

即可

答案 1 :(得分:9)

使用==来比较双打seems like a bad idea

你可以在你要比较的数字上调用setScale:

new BigDecimal ("5.50").setScale(2).equals(new BigDecimal("5.5").setScale (2))

您可以将比例设置为两者中的较大者:

BigDecimal a1 = new BigDecimal("5.051");
BigDecimal b1 = new BigDecimal("5.05");
// wow, this is awkward in Java
int maxScale = Collections.max(new ArrayList() {{ a1.scale(), b1.scale()}});
System.out.println(
  a1.setScale(maxScale).equals(b1.setScale(maxScale)) 
  ? "are equal" 
  : "are different" );

使用compareTo() == 0是最好的答案。上述方法中其中一个数字的比例增加可能是compareMagnitude方法文档提到的“不必要的通货膨胀”:

/**
 * Version of compareTo that ignores sign.
 */
private int compareMagnitude(BigDecimal val) {
    // Match scales, avoid unnecessary inflation
    long ys = val.intCompact;
    long xs = this.intCompact;

当然compareTo更容易使用,因为它已经为您实现了。

答案 2 :(得分:4)

自从Java 1.5以来,用于比较忽略前导零的最简单表达式:

bd1.stripTrailingZeros().equals(bd2.stripTrailingZeros())