Reputation: 13
I'm trying to solve an exercise using the BigDecimal class, but for some values it doesn't respect the correct number of decimal places to show. For the values 5.0 to 12.5 it shows extra decimal places. Any idea why? Thanks in advance.
This is an adapted version of the code:
MathContext mc = new MathContext(2, RoundingMode.UP);
BigDecimal min = new BigDecimal("2.00");
BigDecimal adt = new BigDecimal("0.50");
BigDecimal lim = new BigDecimal("3.00");
for (float f = 5f; f <= 30f ; f += 0.5f) {
String s = Float.toString(f);
BigDecimal hours = new BigDecimal(s);
BigDecimal charge = min.add(hours.subtract(lim).round(mc).multiply(adt));
System.out.println(f + " = " + charge);
}
Output:
5.0 = 3.000
5.5 = 3.250
6.0 = 3.500
6.5 = 3.750
7.0 = 4.000
7.5 = 4.250
8.0 = 4.500
8.5 = 4.750
9.0 = 5.000
9.5 = 5.250
10.0 = 5.500
10.5 = 5.750
11.0 = 6.000
11.5 = 6.250
12.0 = 6.500
12.5 = 6.750
13.0 = 7.00
13.5 = 7.50
14.0 = 7.50
14.5 = 8.00
15.0 = 8.00
15.5 = 8.50
16.0 = 8.50
16.5 = 9.00
17.0 = 9.00
17.5 = 9.50
18.0 = 9.50
18.5 = 10.00
19.0 = 10.00
19.5 = 10.50
20.0 = 10.50
20.5 = 11.00
21.0 = 11.00
21.5 = 11.50
22.0 = 11.50
22.5 = 12.00
23.0 = 12.00
23.5 = 12.50
24.0 = 12.50
24.5 = 13.00
25.0 = 13.00
25.5 = 13.50
26.0 = 13.50
26.5 = 14.00
27.0 = 14.00
27.5 = 14.50
28.0 = 14.50
28.5 = 15.00
29.0 = 15.00
29.5 = 15.50
30.0 = 15.50
Upvotes: 1
Views: 202
Reputation: 10964
The problem is probably a misunderstanding of MathContext
. With MathContext(2, RoundingMode.UP)
you're not saying "I want 2 decimal places", but you say "I want to reduce the precision of my number to 2 digits".
If you have a look at your numbers, the scale (number of decimal places) is 2 where hours - lim >= 10
If you have a detailed look at the two examples hours=12.5
and hours=13.0
//hours = 12.5:
var subtract = hours.subtract("3.00"); // 12.5 - 3.00 = 9.50 (subtract.scale = 2)
var round = subtract.round(mc); // 9.5 (round.scale = 1)
var result = round.multiply("0.50") // 9.5 * 0.50 = 4.750 (result.scale = round.scale + subtract.scale = 3)
//hours = 13.0:
var subtract = hours.subtract("3.00"); // 13.0 - 3.00 = 10.00 (subtract.scale = 2)
var round = subtract.round(mc); // 10 (round.scale = 0)
var result = round.multiply("0.50") // 10 * 0.50 = 5.00 (result.scale = round.scale + subtract.scale = 2)
You see the scale of the rounded decimal becomes 0 as soon as it's value becomes >= 10. The scale of the result of multiply is always the sum of the scale of the two multiplicants.
To set the scale of a BigDecimal
use BigDecimal.setScale(int, RoundingMode)
instead of MathContext
.
Upvotes: 1