Consider this code:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class RoundingTests {
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal(265.345d);
BigDecimal bd2 = new BigDecimal(265.335d);
System.out.println("Setting scale 265.345: " + bd1.setScale(2, RoundingMode.HALF_EVEN));
System.out.println("Setting scale 265.335: " + bd2.setScale(2, RoundingMode.HALF_EVEN));
}
}
The output is:
Setting scale 265.345: 265.35
Setting scale 265.335: 265.33
Now this is exactly the opposite of what I was expecting. With RoundingMode.HALF_EVEN
(also called Bankers rounding) I was expecting both these values to become the value 265.34
Note that I am not using the BigDecimal.round
method on purpose because it also does not what I need. If I add this code (and import java.math.MathContext) :
System.out.println("Rounding 265.345: " + bd1.round(new MathContext(2, RoundingMode.HALF_EVEN)));
System.out.println("Rounding 265.335: " + bd2.round(new MathContext(2, RoundingMode.HALF_EVEN)));
Then the output is:
Rounding 265.345: 2.7E+2
Rounding 265.335: 2.7E+2
This is expected and also explained in BigDecimal setScale and round, but means it's basically useless for my purpose.
Can someone explain the issue with setScale here?
Update: So it was just another floating point problem, with no easy way to fix it instead of using BigDecimals from the start.