Bigdecimal遇到的坑-equals和compareTo

文章目录

      • 前言
      • 1.equals
      • 2.compareTo

前言

运营有个需求,当首付比例为10%的时候没有加融上限
于是我写了以下代码:

if (vo.getRatio().equals(new BigDecimal("0.1")) ){
    return null;
}else {
    xxx
}

后来测试同学来找我了,说“不对丫,首付比例10%的时候还是会有加融上限的丫!”
我心里觉得“不对丫,我加了限制丫”

后来一查报文,前端小哥哥给我传过来的 “Ratio”: 0.10

我一测试 “Ratio”: 0.1 能限制 ,“Ratio”: 0.10 不能限制

如果:
if (vo.getRatio().equals(new BigDecimal(“0.10”)) )

那么: “Ratio”: 0.1 不能限制 ,“Ratio”: 0.10 能限制

难道new BigDecimal(“0.1”) 和new BigDecimal(“0.10”) 不是一个数吗???

且听我说一说,BigDecimal的equals和compareTo

1.equals

/**
 * Compares this {@code BigDecimal} with the specified
 * {@code Object} for equality.  Unlike {@link
 * #compareTo(BigDecimal) compareTo}, this method considers two
 * {@code BigDecimal} objects equal only if they are equal in
 * value and scale (thus 2.0 is not equal to 2.00 when compared by
 * this method).
 *
 * @param  x {@code Object} to which this {@code BigDecimal} is
 *         to be compared.
 * @return {@code true} if and only if the specified {@code Object} is a
 *         {@code BigDecimal} whose value and scale are equal to this
 *         {@code BigDecimal}'s.
 * @see    #compareTo(java.math.BigDecimal)
 * @see    #hashCode
 */
@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());
}

来翻译一下注释:

/**
 *  将{@code BigDecimal}与指定的{@code BigDecimal}相比较。
 *  不像compareTo方法,此方法会比较值和精度,只有在值和精度都相等时才认为相等。
 *  因此,2.0和2.00在此方法中认为是不相等的
 *  
 * @param  参数:要与此{@code BigDecimal}进行比较的val{@code BigDecimal}.
 *           
 * @return 如果两个比较的BigDecimal值和精度都相等则返回true
 * 
 * @see    #compareTo(java.math.BigDecimal)
 * @see    #hashCode
 */

Bigdecimal遇到的坑-equals和compareTo_第1张图片

精度不同就直接返回false了

2.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)} <op> {@code 0)}, where
 * <op> 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;
}

来翻译一下注释:

/**
 * 将{@code BigDecimal}与指定的{@code BigDecimal}相比较,像2.0和2.00这种
 * 值相等但是精度不同的在这个方法里被认为是相等的。这个方法可用于6种运算符的比较:
 *  >=,>,<=,<,==,!=
 *  适用方式 :x.compareTo(y)
 *  
 * 参数:要与此{@code BigDecimal}进行比较的val{@code BigDecimal}.
 * 
 * 返回值:-1 小于 , 0 等于 ,1 大于
 *
 */

BigDecimal的compareTo方法用到了BigDecimal的四个属性值 :

  1. int scale; //有多少位小数(即小数点后有多少位)
  2. int precision; //一共有多少位数字
  3. long intCompact; //字符串去掉小数点后,转为long的值,只有当传的字符串长度小于18时才使用该言
  4. BigInteger intVal; //当传的字符串长度大于等于18时才使用BigInteger表示数字

以new BigDecimal(“12.12”)为例

  1. scale值为2
  2. precision值为4
  3. intCompact值为1212
  4. intVal值为空。
    之所以为空是因为字符串长度没有超18位,所以不启用BigInteger表示

底层原理:
compareTo方法在比较的时候,会判断两个数的精度差,比如2.0和2.00 ,精度差1 ,然后precision-scale 获得值的位数进行比较,再比较不出来就转换成数值进行比较。

还是蛮有意思的,有兴趣的可以看看。

所以,要是比较数值大小或者判断当值==或者!=某个值的时候还是用compareTo比较好。具体情况,具体分析。

你可能感兴趣的:(✈Java)