BigDecimal equals()与compareTo()


157

考虑简单的测试类:

import java.math.BigDecimal;

/**
 * @author The Elite Gentleman
 *
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BigDecimal x = new BigDecimal("1");
        BigDecimal y = new BigDecimal("1.00");
        System.out.println(x.equals(y));
        System.out.println(x.compareTo(y) == 0 ? "true": "false");
    }

}

您可以(有意识地)说x等于y(不是对象引用),但是当您运行程序时,将显示以下结果:

false
true

问:什么是之间的区别compareTo(),并equals()BigDecimalcompareTo可以确定x等于y

PS:我看到BigDecimal在inflate()method上有一个equals()方法。inflate()实际做什么?


1
广告inflate():它不是公共API的一部分,因为它仅操纵内部表示,并且对“外部”没有可见的影响。因此,除非您真的想深入研究实现,否则BigDecimal建议您忽略此方法。
约阿希姆·绍尔

可以在此处
xenteros

Answers:


224

答案在方法的JavaDoc中equals()

compareTo方法不同,此方法BigDecimal仅在两个对象的值和比例相等时才认为它们相等(因此,用此方法比较时,2.0不等于2.00)。

换句话说:equals()检查BigDecimal对象在各个方面是否完全相同。“仅”比较它们的数值。compareTo()

至于为什么 equals()如此行事,这已经在这个SO问题中得到了回答。


24
BigDecimal如果您不仔细阅读JavaDoc,那是非常棘手的部分。:)-从中我们得到了一些奇怪的错误,直到我们意识到了区别。
托马斯,

3
当直观的事情不正确时,标准API的许多部分都会“不直观地”起作用。BigDecimal就是这样一件事。因此,应始终检查JavaDoc。至少一旦您发现一些奇怪的事情发生了。
约阿希姆·绍尔

7
滑稽。在阅读完您的答案后,我刚刚检查了Comparable,它指出与equals的一致性“强烈建议(但不是必需的)”
SJuan76


8
@StephenC我认为存在这种不一致是不正确的
Matt R

1

我看到BigDecimal在equals()方法上有一个inflate()方法。inflate()实际上做什么?

基本上,如有必要,inflate()调用BigInteger.valueOf(intCompact),即它创建未缩放的值,该值存储为BigIntegerfrom long intCompact。如果您不需要它,BigInteger并且未缩放的值正好适合long BigDecimal于尝试尽量节省空间。


我不知道你写了什么(尤其是最后一句话)。
Buhake Sindi

@The Elite Gentlement最后一句话应该说是内部BigDecimal将其未缩放的值同时保留在long和中BigInteger。如果在BigInteger内部不需要它,则不会创建它,但是如果需要它(例如,当equals遇到膨胀的和非膨胀的BigDecimal) inflate()`来创建它时)-总结:inflate()必要时处理内部转换,因为是私人的,对班级的用户来说无关紧要
Thomas Thomas

1

我相信正确的答案是使两个数字(BigDecimals)具有相同的小数位数,然后我们可以决定它们的相等性。例如,这两个数字相等吗?

1.00001 and 1.00002

好吧,这取决于规模。在小数位数5(小数点后5位)上,否,它们不相同。但在较小的十进制精度(小于等于4的小数位)上,它们被视为相等。因此,我建议使两个数字的比例相等,然后进行比较。


-10

您还可以比较双值

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());

5
请尽可能避免这种解决方案。甚至双打也应与“ε”进行比较。拥有BigDecimal并将其作为双精度进行比较是没有道理的。您很有可能会开枪射击自己的腿。
Vadim Kirilchuk '18

必须使用epsillons来比较双倍值
Bishwajit Purkaystha '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.