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:
}
The value of the number represented by the BigDecimal is therefore (unscaledValue × 10 -scale). The BigDecimal class provides operations for arithmetic, scale manipulation, rounding, comparison, hashing, and format conversion. The toString() method provides a canonical representation of a BigDecimal.
Parameters: The method accepts a single parameter val of Double data type and refers to the value that needs to be translated into a BigDecimal value. Return value: The method returns a BigDecimal value which is equal to or approximately equal to Double val.
The BigDecimal class provides operations on double numbers for arithmetic, scale handling, rounding, comparison, format conversion and hashing.
The toEngineeringString () method may be used for presenting numbers with exponents in engineering notation, and the setScale method may be used for rounding a BigDecimal so it has a known number of digits after the decimal point. The digit-to-character mapping provided by Character.forDigit is used. string representation of this BigDecimal.
If you want to know if two BigDecimal
s 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.
Use stripTrailingZeros()
. This returns an equivalent BigDecimal
with the scale minimized and is the simplest way to get a canonical representation. It's better than setScale()
because it avoids any issues with rounding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With