Search code examples
javamathequalsbigdecimalcanonicalization

Canonical representation of a BigDecimal


What is the simplest way to reduce a Java BigDecimal containing an arbitrary value to a canonical form so that two BigDecimal's representing the same number will compare equal using the equals() method?

I am parsing my numbers from arbitrary strings using code like this:

BigDecimal x = new BigDecimal(string1, MathContext.DECIMAL64);
BigDecimal y = new BigDecimal(string2, MathContext.DECIMAL64);

Since (string1, string2) are arbitrary, they could be, e.g., ("1", "1.0000") or ("-32.5", "1981")...

What I'm looking for is the simplest (shortest/cleanest code) implementation of the method canonicalize for which the above assertion

assert x.compareTo(y) != 0 ||
    (canonicalize(x).equals(canonicalize(y)) && 
     x.compareTo(canonicalize(x)) == 0 && y.compareTo(canonicalize(y)) == 0);

will succeed...:

public static BigDecimal canonicalize(BigDecimal b) {
    // TODO:
}

Solution

  • If you want to know if two BigDecimals are equal regardless of scale, just use .compareTo()

    public static boolean bigDecimalEquals(BigDecimal b1, BigDecimal b2) {
        return b1.compareTo(b1) == 0;
    }
    

    It specifically recommends this in the Javadoc

    Two 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 (<, ==, >, >=, !=, <=).


    If you actually want to convert the BigDecimal so that .equals() will work, just use the setScale method.