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.
You might want to change your code to use BigDecimal.valueOf()
instead of new BigDecimal()
.
The code
Double dValue = 265.345d;
Double dValue2 = 265.335d;
BigDecimal value = BigDecimal.valueOf(dValue);
BigDecimal bd1 = new BigDecimal(265.345d);
BigDecimal bd2 = new BigDecimal(265.335d);
BigDecimal value2 = BigDecimal.valueOf(dValue2);
System.out.println("BigDecimal.valueOf(dValue);");
System.out.println(value.toPlainString());
System.out.println(String.valueOf(dValue));
value = value.setScale(2, BigDecimal.ROUND_HALF_EVEN);
System.out.println(value);
System.out.println("BigDecimal.valueOf(dValue2);");
System.out.println(value2.toPlainString());
System.out.println(String.valueOf(dValue2));
value2 = value2.setScale(2, BigDecimal.ROUND_HALF_EVEN);
System.out.println(value2);
System.out.println("BigDecimal bd1 = new BigDecimal(265.345d);");
System.out.println(bd1.setScale(2, BigDecimal.ROUND_HALF_EVEN));
System.out.println("BigDecimal bd2 = new BigDecimal(265.335d);");
System.out.println(bd2.setScale(2, BigDecimal.ROUND_HALF_EVEN));
outputs :
BigDecimal.valueOf(dValue);
265.345
265.345
265.34
BigDecimal.valueOf(dValue2);
265.335
265.335
265.34
BigDecimal bd1 = new BigDecimal(265.345d);
265.35
BigDecimal value2 = BigDecimal.valueOf(dValue2);
265.33
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