I have the following requirement to round amounts:
1.2448 -> 1.25
3.349 -> 3.35
0.474 -> 0.47
I have tried all the possible modes of the BigDecimal.setScale(2, RoundingMode.) method, without any success. Here is the result:
UP: 1.25, 3.35, 0.48
HALF_UP: 1.24, 3.35, 0.47
CEILING: 1.25, 3.35, 0.48
FLOOR: 1.24, 3.34, 0.47
DOWN: 1.24, 3.34, 0.47
HALF_DOWN: 1.24, 3.35, 0.47
HALF_EVEN: 1.24, 3.35, 0.47
I have also tried to use BigDecimal.round(), with not good result neither.
How can I round the amounts in the required way ?
Edit:
Why do I actually need to round in this seemingly bizarre way?
In a new software we are developing, we need to reproduce the rounding behavior or a legacy software (which is the way business wants rounding to be done)
Solution:
I absolutely want to stay with BigDecimals for all my calculations.
So, at the end I came up with this simple function to do the "progressive" rounding:
public static BigDecimal roundAmount(BigDecimal amount) {
for (int i = amount.scale(); i >= 2; i--) {
amount = amount.setScale(i, RoundingMode.HALF_UP);
}
return amount;
}
What you are trying to do is round each digit progressively. 1.2448 -> 1.245 -> 1.25.
This means the smallest number needed to round up is .nn4444444444444445 which is close to adding 1/2 - 4/9 after scaling which is 1/18.
Whenever I have seen someone suggest this it has been incorrect, but it is easy to calculate.
for (double d : new double[]{1.2448, 3.349, 0.474}) {
double rounded = Math.round(d * 1e2 + 1.0 / 18) / 1e2;
System.out.printf("%s should be %.2f rounded half up and is %s%n", d, d, rounded);
}
prints
1.2448 should be 1.24 rounded half up and is 1.25
3.349 should be 3.35 rounded half up and is 3.35
0.474 should be 0.47 rounded half up and is 0.47
As you can see, the need to add 1/18th is an odd number but that is what you are effectively doing when you round each digit up progressively.