关于java:为什么不能使用-BigDecimal-的-equals-方法做等值比较

3次阅读

共计 4783 个字符,预计需要花费 12 分钟才能阅读完成。

前言

BigDecimal 是 java.math 包中提供的一种能够用来进行准确运算的类型。所以,在领取、电商等业务中,BigDecimal 的应用十分频繁。而且其外部自带了很多办法,如加,减,乘,除等运算办法都是能够间接调用的。除了须要用 BigDecimal 示意数字和进行数字运算以外,代码中还常常须要对于数字进行相等判断。

那么为什么会有这样的要求呢🤔~ 其中的神秘是什么呢🤔~ 请各位小伙伴听我娓娓道来 …

BigDecimal 做等值比拟

    public static void main(String[] args) {BigDecimal bigDecimal1 = new BigDecimal(1);
        BigDecimal bigDecimal2 = new BigDecimal(1);

        if(bigDecimal1 == bigDecimal2){// 等值比拟}
    }

置信聪慧的小伙伴一眼就可以看进去下面的代码是有问题的,因为 BigDecimal 是对象,不能应用 == 来做等值判断。

如果咱们应用 BigDecimal 的 equals 办法做等值比拟是不是能够呢?👇

    public static void main(String[] args) {BigDecimal bigDecimal1 = new BigDecimal(1);
        BigDecimal bigDecimal2 = new BigDecimal(1);

        if(bigDecimal1.equals(bigDecimal2)){// 等值比拟}
    }

这里我先卖个关子,咱们跑跑代码来看看能不能用 BigDecimal 的 equals 办法做等值比拟 (●’◡’●),

    public static void main(String[] args) {BigDecimal bigDecimal1 = new BigDecimal(1);
        BigDecimal bigDecimal2 = new BigDecimal(1);
        System.out.println(bigDecimal1.equals(bigDecimal2));

        BigDecimal bigDecimal3 = new BigDecimal(1);
        BigDecimal bigDecimal4 = new BigDecimal(1.0);
        System.out.println(bigDecimal3.equals(bigDecimal4));

        BigDecimal bigDecimal5 = new BigDecimal("1");
        BigDecimal bigDecimal6 = new BigDecimal("1.0");
        System.out.println(bigDecimal5.equals(bigDecimal6));

    }

咱们能够发现,在应用 BigDecimal 的 equals 办法对 1 和 1.0 进行比拟的时候:应用 int、double 定义 BigDecimal 后果是 true;应用 String 定义 BigDecimal 后果是 false,为什么会呈现这种状况呢?

咱们一起来看看 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());
    }

其实咱们从办法的正文中就能找到答案:equals 办法会比拟两局部内容,别离是值(value)和标度(scale),也就是说 bigDecimal5 和 bigDecimal6 的值尽管雷同,然而标度是不一样的。

咱们打个断点,debug 一下看看~

咱们能够看见 bigDecimal5 的标度值是 0,而 bigDecimal6 的标度值是 1,所以 bigDecimal5 和 bigDecimal6 的比拟后果是 false (●ˇ∀ˇ●)

那么这时候又产生了一个疑难:为什么标度不同呢?🤔

嘻嘻~ 各位小伙伴稍安勿躁,请听我娓娓道来~

BigDecimal 一共有以下 4 个构造方法:

  • BigDecimal(int)
  • BigDecimal(double)
  • BigDecimal(long)
  • BigDecimal(String)

其中最容易了解的就是 BigDecimal(int) 和 BigDecimal(long),因为是整数,所以标度就是 0(源码如下👇):

 /**
     * Translates an {@code int} into a {@code BigDecimal}.  The
     * scale of the {@code BigDecimal} is zero.
     *
     * @param val {@code int} value to be converted to
     *            {@code BigDecimal}.
     * @since  1.5
     */
    public BigDecimal(int val) {
        this.intCompact = val;
        this.scale = 0;
        this.intVal = null;
    }

``````
 /**
     * Translates a {@code long} into a {@code BigDecimal}.  The
     * scale of the {@code BigDecimal} is zero.
     *
     * @param val {@code long} value to be converted to {@code BigDecimal}.
     * @since  1.5
     */
    public BigDecimal(long val) {
        this.intCompact = val;
        this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
        this.scale = 0;
    }

而对于 BigDecimal (double) 来说,当咱们应用 new BigDecimal (0.1) 创立一个对象的时候,其实创立进去的对象的值并不是等于 0.1,而是等于 0.1000000000000000055511151231257827021181583404541015625

咱们再打个断点,debug 一下看看标度值是多少

咱们能够看到标度值是 55,这个值是怎么来的呢?其实很简略,这个标度值就是这个数字的位数,其余的浮点数也同样的情理。对于 new BigDecimal (1.0),和 new BigDecimal (1.00) 这样的模式来说,因为他实质上也是个整数,所以他创立进去的数字的标度就是 0。

最初咱们再看看 BigDecimal(String),当咱们应用 new BigDecimal (“0.1”) 创立一个 BigDecimal 的时候,其实创立进去的值正好就是等于 0.1 的。那么他的标度也就是 1;如果应用 new BigDecimal (“0.10000”),那么创立进去的数就是 0.10000,标度也就是 5。

讲到这里置信各位小伙伴也明确了为什么 bigDecimal5 和 bigDecimal6 用 equals 办法做等值比拟的后果是 false 了 O(∩\_∩)O

如果咱们只想判断两个 BigDecimal 的值是否相等,那么该如何判断呢?

在 BigDecimal 中也为咱们提供了一个办法 —— compareTo 办法,这个办法就能够只比拟两个数字的值,如果两个数相等,则返回 0。

咱们把 equals 换成 compareTo 后能够发现,bigDecimal5 和 bigDecimal6 等值比拟的后果是 0,也就是说明这二者的值是相等的。

P.S. 所以咱们在做等值比拟的时候不要轻易用 BigDecimal 的 equals 办法,如果只是要对数值作比拟,就果决抉择 compareTo 办法就搞定拉~

小结

自己教训无限,有些中央可能讲的没有特地到位,如果您在浏览的时候想到了什么问题,欢送在评论区留言,咱们后续再一一探讨🙇‍

如果本文对你有帮忙的话,请不要悭吝你的赞,谢谢!

正文完
 0