写点什么

开源一夏 |为什么 BigDecimal 比较大小一定要用 compareTo

  • 2022 年 8 月 31 日
    北京
  • 本文字数:1842 字

    阅读完需:约 6 分钟

开源一夏 |为什么BigDecimal比较大小一定要用compareTo

日常工作中,当涉及精度较高的数值时,通常会用到 BigDecimal 类型,那么关于 BigDecimal 的比较大小更是会经常用到,在比较大小时究竟是用 compareTo 还是 equals 呢?这里我们主要来看这两种比较方式的区别,怎么选择,大家自行决定即可,哈哈。

BigDecimal

BigDecimal,是一种 java.math 包中提供的一种可以用来进行精确运算的类型,在进行金额表示、金额计算等场景,不能使用 double、float 等类型,而是要使用对精度支持的更好的 BigDecimal。

所以,很多支付、电商、金融等业务中,BigDecimal 的使用非常频繁,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的,代码中还经常需要对于数字进行相等判断。

BigDecimal 比较

==比较

==是比较常用的数值比较的方式,下面我们来看一下 BigDecimal 用==比较的结果

BigDecimal bigDecimal = new BigDecimal(1);BigDecimal bigDecimal1 = new BigDecimal(1);System.out.println(bigDecimal == bigDecimal1);//false
复制代码

运行结果如图

可以看到用==直接比较肯定是无法得到自己想要的情况的,因为 BigDecimal 是对象,所以是无法用==来比较两个数字的值是否相等。

== 可以用来比较基本类型的数值,例如:

int a = 1;int b = 1;System.out.println(a==b);//true
复制代码


== 用来比较对象,比较的是引用对象的引用地址,针对上面的 BigDecimal 比较的情况我们来 debug 看一下

BigDecimal bigDecimal = new BigDecimal(1);BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal == bigDecimal1);//false
复制代码

debug 结果如图

我们可以看到两个对象的引用地址不一样,所以返回 false。

equals 比较

首先来看一组代码比较结果

        BigDecimal bigDecimal = new BigDecimal(1);        BigDecimal bigDecimal1 = new BigDecimal(1);        System.out.println("result1:"+bigDecimal.equals(bigDecimal1));
BigDecimal bigDecimal2 = new BigDecimal(1); BigDecimal bigDecimal3 = new BigDecimal(1.0); System.out.println("result2:"+bigDecimal2.equals(bigDecimal3));
BigDecimal bigDecimal4 = new BigDecimal("1"); BigDecimal bigDecimal5 = new BigDecimal("1.0"); System.out.println("result3:"+bigDecimal4.equals(bigDecimal5));
复制代码

结果如图

通过结果可以看出 BigDecimal 在进行 equals 比较时,有的时候是 true(当使用 int、double 定义 BigDecimal 时),有的时候是 false(当使用 String 定义 BigDecimal 时)。

在 BigDecimal 的 JavaDoc 注释中提到,equals 和 compareTo 比较不太一样,equals 比较时会比较 value and scale,所以再来看上面 bigDecimal4 和 bigDecimal5 的结果就明白了

那么为什么用 int 、double 定义 BigDecimal 时就一样呢?

这里我把代码参数值改一下,方便后面 debug 区分

        BigDecimal bigDecimal = new BigDecimal(1);        BigDecimal bigDecimal1 = new BigDecimal(1);        System.out.println("result1:"+bigDecimal.equals(bigDecimal1));
BigDecimal bigDecimal2 = new BigDecimal(2); BigDecimal bigDecimal3 = new BigDecimal(2.0); System.out.println("result2:"+bigDecimal2.equals(bigDecimal3));
BigDecimal bigDecimal4 = new BigDecimal("3"); BigDecimal bigDecimal5 = new BigDecimal("3.0"); System.out.println("result3:"+bigDecimal4.equals(bigDecimal5));
复制代码

用 int 时 debug 结果图

其中 scale 和 xDec.scale 的值都是 0。

用 double 时 debug 结果图

其中 scale 和 xDec.scale 的值都是 0。

用 string 时 debug 结果图

其中 bigDecimal4 的 scale 是 0,而 bigDecimal5 的 scale 是 1,这样比较的结果就是 false 了。

前面,我们解释了 BigDecimal 的 equals 方法,其实不只是会比较数字的值,还会对其标度进行比较。

所以,当我们使用 equals 方法判断判断两个数是否相等的时候,是极其严格的。

compareTo 比较

针对上面 equals 比较比较严格的情况,如果只想比较值呢,BigDecimal 为我们提供了 compareTo 方法。

此时我们看到 bigDecimal6 和 bigDecimal7 比较的值为 0,即相等。

我们可以看到 BigDecimal 中 compareTo 的 JavaDoc 注释,compareTo 只比较值,其中返回结果:-1 表示小于,0 表示等于,1 表示大于

为了更好的理解 compareTo,我们来 debug 一下看看

可以看到当 scale 和 val.scale 不相等时直接进入下面数值比较,不再比较 scale 是否相等。

建议

一般 BigDecimal 值的比较用 compareTo 就好,用 equals 比较的话可能会得到不是你想要的结果而自己又不曾意识到。

发布于: 刚刚阅读数: 8
用户头像

让技术不再枯燥,让每一位技术人爱上技术 2022.07.22 加入

还未添加个人简介

评论

发布
暂无评论
开源一夏 |为什么BigDecimal比较大小一定要用compareTo_开源_六月的雨在infoQ_InfoQ写作社区