Java中用于零值(BigDecimal / Double)的等号运算符

43

关于0和0.0的等号运算符,有一些有趣的观察。

  1. new Double(0.0).equals(0)返回false,而new Double(0.0).equals(0.0)返回true。

  2. BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0))返回false,而BigDecimal.ZERO.equals(BigDecimal.valueOf(0))返回true。

看起来在两种情况下都是进行了字符串比较。能否有人详细解释一下呢?

谢谢。

7个回答

71
BigDecimal的“equals”方法会比较数值和小数位数。如果你只想比较数值(0 == 0.0),你应该使用compareTo方法。
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0.0)) == 0 //true
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0)) == 0 //true

查看javadoc
至于Double比较,如其他答案所解释的,你正在比较一个Double和一个Integer,在new Double(0.0).equals(0)中,它返回false,因为这两个对象具有不同的类型。参考JDK 7中equals方法的代码如下:
public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

在你的情况下,(obj instanceof Double) 是 false。

7
  1. The 0 in your first expression is interpreted as an int, which may be autoboxed into an Integer, but not to a Double. So the type of the two is different, hence they are not equal. OTOH 0.0 is a double, which is autoboxed into a Double, so the two operands are deemed equal.

  2. BigDecimals also contain a scale (i.e. number of digits to the right of the decimal separator dot). BigDecimal.ZERO has the value of "0", so its scale is 0. Hence it is not equal to "0.0", whose scale is 1.
    If you want to compare values, use BigDecimal.compareTo:

    BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0.0)) == 0
    BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0)) == 0
    

1
new Double(0.0).equals(0); //false

由于你传递的参数是整数。并且在 Double 类中,equals() 方法使用 instance of 运算符来检查参数是否为 Double 实例。

Doubleequals() 方法。

if (!(argument instanceof Double))
  return false;

你传递的参数是整数,而不是双精度浮点数的实例,因此返回false。

1

new Double(0.0).equals(0)实际上会被封装成类似这样的形式:

new Double(0.0).equals(Integer.valueOf(0))

除非给定另一个Double实例,否则Double.equals(...)永远不会返回true。


0
new Double(0.0).equals(0)

这行代码比较了一个非精确零值的double类型数值和整型0。

BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0))

在 equals 操作中,BigDecimal 会比较其标度长度。


0
为了提高性能,BigDecimal和BigInteger会缓存小的数值0到15(BigDecimal没有小数部分)。
BigDecimal.ZERO将会是new BigDecimal(BigInteger.ZERO, 0, 0, 1),而valueOf方法通常会从缓存中选择0到15的数值 :)

0
please try doublevalue instead of compareto if you feel is not as beautiful and readable as or simply need an alternative like below:

BigDecimal a = new BigDecimal("0.00");
BigDecimal b = new BigDecimal("0.0");
BigDecimal c = new BigDecimal("0");

if(a.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("a equals");
}

if(b.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("b equals");
}

if(c.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("c equals");
} 

2
将 BigDecimal 转换为 double 可能会导致精度损失,而接近零但非零的 BigDecimal 转换为 Double 可能会变成 0。您应该使用 BigDecimal 中的 compareTo 方法进行比较。 - Mosty Mostacho

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