new BigDecimal(0.82) is not actually 0.82, because you're passing a double value -- the double closest to 0.82, which is not exactly 0.82 -- to the constructor, so new BigDecimal(0.82) is a BigDecimal equal to the double closest to 0.82.
Instead, use new BigDecimal("0.82").
new BigDecimal(0.82) is not actually 0.82, because you're passing a double value -- the double closest to 0.82, which is not exactly 0.82 -- to the constructor, so new BigDecimal(0.82) is a BigDecimal equal to the double closest to 0.82.
Instead, use new BigDecimal("0.82").
The problem is that you use the constructor BigDecimal#BigDecimal(double). It returns a BigDecimal that represents the double's binary floating-point value (see its documentation). However, 0.82 isn't representing the value 0.82 but
0.81999999999999995115018691649311222136020660400390625
Because of that .setScale(5, BigDecimal.ROUND_HALF_DOWN) actually changes the value, not only the scale. The resulting value after applying the method is
0.82000
The compareTo method ignores the scale but not different values. As explained, your two BigDecimal actually represent different values. Thus the compareTo does not return 0:
0.82000 != 0.81999999999999995115018691649311222136020660400390625
See the documentation of the method:
Two
BigDecimalobjects that are equal in value but have a different scale (like2.0and2.00) are considered equal by this method. [...]
To be short:
firstBigDecimal.compareTo(secondBigDecimal) < 0 // "<"
firstBigDecimal.compareTo(secondBigDecimal) > 0 // ">"
firstBigDecimal.compareTo(secondBigDecimal) == 0 // "=="
firstBigDecimal.compareTo(secondBigDecimal) != 0 // "!="
firstBigDecimal.compareTo(secondBigDecimal) >= 0 // ">="
firstBigDecimal.compareTo(secondBigDecimal) <= 0 // "<="
Every object of the Class BigDecimal has a method compareTo you can use to compare it to another BigDecimal. The result of compareTo is then compared > 0, == 0 or < 0 depending on what you need. Read the documentation and you will find out.
The operators ==, <, > and so on can only be used on primitive data types like int, long, double or their wrapper classes like Integerand Double.
From the documentation of compareTo:
Compares this
BigDecimalwith the specifiedBigDecimal.Two
BigDecimalobjects 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 (<, ==, >, >=, !=, <=). The suggested idiom for performing these comparisons is:(x.compareTo(y) <op> 0), where<op>is one of the six comparison operators.Returns: -1, 0, or 1 as this BigDecimal is numerically less than, equal to, or greater than val.
From the javadoc of BigDecimal
equals
public boolean equals(Object x)Compares this
BigDecimalwith the specifiedObjectfor equality. UnlikecompareTo, this method considers twoBigDecimalobjects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).
Simply use compareTo() == 0
The simplest expression to compare ignoring trailing zeros is since Java 1.5:
bd1.stripTrailingZeros().equals(bd2.stripTrailingZeros())
You need to use the String constructor to get the correct scales, because the BigDecimal(double) will get the small scale possible
translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value. The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer.
More precision about the documentations :
BigDecimal.equals(Object)
Compares this BigDecimal with the specified Object for equality. 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).
BigDecimal.compareTo(BigDecimal)
Compares this BigDecimal with the specified BigDecimal. 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 (<, ==, >, >=, !=, <=). The suggested idiom for performing these comparisons is: (x.compareTo(y) 0), where is one of the six comparison operators.
You will find that the equals use the scale for the comparison, giving some "strange" result.
BigDecimal bd1 = new BigDecimal("2"); //scale 0
BigDecimal bd2 = new BigDecimal("2.00"); //scale 2
bd1.equals(bd2); //false
bd1.compareTo(bd2); //0 => which means equivalent
It's better to use compareTo for BigDecimal. This method will return a number greater than zero if a > b, 0 if a == b, and less than zero if a < b
The answer is in the JavaDoc of the equals() method:
Unlike
compareTo, this method considers twoBigDecimalobjects 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.
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.