1. 程式人生 > >BigDecimal比較大小注意事項(equals)

BigDecimal比較大小注意事項(equals)

在專案中使用BigDecimal的equals方法比較大小時,結果不為true,直接上示例

    public static void main(String[] args) {
        BigDecimal a = new BigDecimal(0.00);
        BigDecimal b = new BigDecimal(0);

        boolean result = a.equals(b);
        System.out.println("a equals b -->" + result);

        BigDecimal c = new BigDecimal("0.00");
        BigDecimal d = new BigDecimal("0");

        boolean result1 = c.equals(d);
        System.out.println("c equals d -->" + result1);
    }

結果:

a equals b -->true
c equals d -->false

可以看到a和b比較結果是true,c和d比較的結果為fasle

c、d使用傳入字串的構造器(等同於資料庫查詢出來的值)

專案中從資料庫查詢出來的值進行比較時(上例中c、d)顯然不是我們期望的結果,因此修改為如下方法

boolean result2 = c.compareTo(d) == 0;
System.out.println("c compareTo d -->" + result2);

結果:

c compareTo d -->true

我們來看下構造器:

    public BigDecimal(String val) {
        this(val.toCharArray(), 0, val.length());
    }

該構造器的註釋:

可以看出,“0”傳入構造器得到的是0且沒有小數位,“0.00”傳入構造器得到的是0.00,含有2位小數

再看看equals方法:

 @Override
    public boolean equals(Object x) {
        if (!(x instanceof BigDecimal))
            return false;
        BigDecimal xDec = (BigDecimal) x;
        if (x == this)
            return true;
        if (scale != xDec.scale)
            return false;
        long s = this.intCompact;
        long xs = xDec.intCompact;
        if (s != INFLATED) {
            if (xs == INFLATED)
                xs = compactValFor(xDec.intVal);
            return xs == s;
        } else if (xs != INFLATED)
            return xs == compactValFor(this.intVal);

        return this.inflated().equals(xDec.inflated());
    }

可以清晰看到equals方法比較了小數位數 -----> if (scale != xDec.scale) return false; 

到這裡可以理解上面C、Dequals比較結果為什麼是false了

再來看看compareTo方法

/**
     * Compares this {@code BigDecimal} with the specified
     * {@code BigDecimal}.  Two {@code BigDecimal} objects that are
     * equal in value but have a different scale (like 2.0 and 2.00)
     * are considered equal by this method.  This method is provided
     * in preference to individual methods for each of the six boolean
     * comparison operators ({@literal <}, ==,
     * {@literal >}, {@literal >=}, !=, {@literal <=}).  The
     * suggested idiom for performing these comparisons is:
     * {@code (x.compareTo(y)} &lt;<i>op</i>&gt; {@code 0)}, where
     * &lt;<i>op</i>&gt; is one of the six comparison operators.
     *
     * @param  val {@code BigDecimal} to which this {@code BigDecimal} is
     *         to be compared.
     * @return -1, 0, or 1 as this {@code BigDecimal} is numerically
     *          less than, equal to, or greater than {@code val}.
     */
    public int compareTo(BigDecimal val) {
        // Quick path for equal scale and non-inflated case.
        if (scale == val.scale) {
            long xs = intCompact;
            long ys = val.intCompact;
            if (xs != INFLATED && ys != INFLATED)
                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
        }
        int xsign = this.signum();
        int ysign = val.signum();
        if (xsign != ysign)
            return (xsign > ysign) ? 1 : -1;
        if (xsign == 0)
            return 0;
        int cmp = compareMagnitude(val);
        return (xsign > 0) ? cmp : -cmp;
    }

可以看到,分了2種情況,一種是含有小數位相同,另一種時不相同的情況。所以不管2個數的小數位是否相同,都會進行值的比較。