197

Consider the simple test class:

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");
    }

}

You can (consciously) say that x is equal to y (not object reference), but when you run the program, the following result shows:

false
true

Question: What's the difference between compareTo() and equals() in BigDecimal that compareTo can determine that x is equal to y?

PS: I see that BigDecimal has an inflate() method on equals() method. What does inflate() do actually?

Jonas
  • 121,568
  • 97
  • 310
  • 388
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • 1
    Ad `inflate()`: it's not part of the public API because it only manipulates the internal representation and has no visible effect to the "outside". So unless you really want to study the implementation of `BigDecimal` in-depth, I'd suggest you ignore this method. – Joachim Sauer Jul 22 '11 at 08:34
  • A short explanation and source code snippets can be found [here](http://stackoverflow.com/a/39163942/4723795) – xenteros Sep 02 '16 at 14:40

4 Answers4

278

The answer is in the JavaDoc of the equals() method:

Unlike compareTo, this method considers two 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).

In other words: equals() checks if the BigDecimal objects are exactly the same in every aspect. compareTo() "only" compares their numeric value.

As to why equals() behaves this way, this has been answered in this SO question.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 31
    That's a very tricky portion of `BigDecimal` if you don't read the JavaDoc carefully. :) - We got some strange bugs from this until we realized the difference. – Thomas Jul 22 '11 at 08:04
  • 3
    Many parts of the standard API happen to act "unintuitively", when the intuitive thing would not be correct. `BigDecimal` is one such thing. Therefore one should always check the JavaDoc. *At least* once your find out something strange is going on. – Joachim Sauer Jul 22 '11 at 08:05
  • 7
    Funny. After reading your answer I just checked Comparable and it states that consistence with equals "is strongly recommended (but not required)" – SJuan76 Jul 22 '11 at 08:10
  • 4
    @SJuan76 - it is important to understand why it is *correct* that this inconsistency should exist for `BigDecimal` ... – Stephen C Jul 22 '11 at 08:30
  • 4
    I've asked why: http://stackoverflow.com/questions/14102083/why-is-bigdecimal-equals-specified-to-compare-both-value-and-scale-individually – bacar Dec 31 '12 at 13:16
  • 9
    @StephenC I think it's *incorrect* that this inconsistency exists. – Matt R Jul 11 '14 at 08:00
  • 1
    @MattR: There are two reasons for the behavior. First of all, the values 1.20 and 1.2 may represent the same value, but they do not behave identically in all contexts. For example, calling `toString()` on them will yield different values. That may be a sufficient difference to regard them as unequal. Secondly, it the two values compare as equal, then the values from the hash function would have to match as well. The way BigDecimal values 1.20 and 1.2 are stored, however, is sufficiently different that computing matches hash values would be tricky. – supercat May 26 '18 at 18:22
  • @supercat We...discussed this four years ago: https://stackoverflow.com/questions/14102083/why-is-bigdecimal-equals-specified-to-compare-both-value-and-scale-individually – Matt R May 31 '18 at 11:23
  • 1
    The longer I work with `java.lang.BigDecimal` the more I regret not using the money on my system as an int/long representation of the cents – JorgeGarza Dec 09 '18 at 23:32
2

I believe that the correct answer would be to make the two numbers (BigDecimals), have the same scale, then we can decide about their equality. For example, are these two numbers equal?

1.00001 and 1.00002

Well, it depends on the scale. On the scale 5 (5 decimal points), no they are not the same. but on smaller decimal precisions (scale 4 and lower) they are considered equal. So I suggest make the scale of the two numbers equal and then compare them.

Mr.Q
  • 4,316
  • 3
  • 43
  • 40
2

I see that BigDecimal has an inflate() method on equals() method. What does inflate() do actually?

Basically, inflate() calls BigInteger.valueOf(intCompact) if necessary, i.e. it creates the unscaled value that is stored as a BigInteger from long intCompact. If you don't need that BigInteger and the unscaled value fits into a long BigDecimal seems to try to save space as long as possible.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • I have no idea what you wrote (especially with the last sentence). – Buhake Sindi Jul 22 '11 at 08:30
  • @The Elite Gentlement The last sentence should just say that internally `BigDecimal` keeps its unscaled value in a `long` as well as a `BigInteger`. If the `BigInteger` is not needed internally it is not created but if it is needed (e.g. when `equals` encounters an inflated and a non-inflated `BigDecimal) `inflate()` is used to create it. - To sum it up: `inflate()` handles internal conversions if necessary and since it is private it shouldn't matter for users of the class. – Thomas Jul 22 '11 at 09:01
-15

You can also compare with double value

BigDecimal a= new BigDecimal("1.1"); BigDecimal b =new BigDecimal("1.1");
System.out.println(a.doubleValue()==b.doubleValue());
Rashmi singh
  • 151
  • 1
  • 5