I'm having trouble with rounding. Specifically, after reading all the javadoc, I was expecting the following code:
int n = (integer between 0 and 9, included)
new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
to return n + 0.56
. Instead, these are the return values for n
from 0
to 4
:
new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
0.56
new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
1.55
new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
2.56
new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
3.56
new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
4.55
I have also tried to change the rounding mode:
int n = (integer between 0 and 9, included)
new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
expecting n + 0.55
as a result for each and every n
. Instead, the return values are exactly the same as the previous example:
new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
0.56
new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
1.55
new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
2.56
new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
3.56
new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
4.55
Am I missing something?
The problem you have is that double is not a precise representation and you are round based on this imprecise number.
BigDecimal bd = new BigDecimal(1.555d);
System.out.println("bd=" + bd);
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println("after rounding bd=" + bd);
double d = bd.doubleValue();
System.out.println("after rounding d=" + d);
prints
bd=1.5549999999999999378275106209912337362766265869140625
after rounding bd=1.55
after rounding d=1.55
however
BigDecimal bd = BigDecimal.valueOf(1.555d);
System.out.println("bd=" + bd);
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println("after rounding bd=" + bd);
double d = bd.doubleValue();
System.out.println("after rounding d=" + d);
prints
bd=1.555
after rounding bd=1.56
after rounding d=1.56
This works because BigDecimal.valueOf
does some extra rounding based on how double would appear if you printed it.
However I wouldn't use BigDecimal unless performance/simplicity is not an issue.
double d = 1.555d;
System.out.println("d=" + d);
d = roundToTwoPlaces(d);
System.out.println("after rounding d=" + d);
public static double roundToTwoPlaces(double d) {
return ((long) (d < 0 ? d * 100 - 0.5 : d * 100 + 0.5)) / 100.0;
}
prints
d=1.555
after rounding d=1.56
For more details Double your money again compares the performance of different ways of rounding.
@Peter Lawrey I looked at your examples and wrote a quick program comparing the simple approach that you posted along with all the methods for RoundingMode. The code is here for anyone interested, this will clearly show the differences:
[RoundingMode.java] https://gitlab.com/bobby.estey/java/-/blob/master/maven/jdk14/src/main/java/mathematics/RoundingModeExamples.java
Results:
lowDouble: 1.55553
simple - lowDouble: 1.5555
RoundingMode.UP - lowDouble: 1.5556
RoundingMode.DOWN - lowDouble: 1.5555
RoundingMode.CEILING - lowDouble: 1.5556
RoundingMode.FLOOR - lowDouble: 1.5555
RoundingMode.HALF_UP - lowDouble: 1.5555
RoundingMode.HALF_DOWN - lowDouble: 1.5555
RoundingMode.HALF_EVEN - lowDouble: 1.5555
highDouble: 1.55555
simple - highDouble: 1.5556
RoundingMode.UP - highDouble: 1.5556
RoundingMode.DOWN - highDouble: 1.5555
RoundingMode.CEILING - highDouble: 1.5556
RoundingMode.FLOOR - highDouble: 1.5555
RoundingMode.HALF_UP - highDouble: 1.5555
RoundingMode.HALF_DOWN - highDouble: 1.5555
RoundingMode.HALF_EVEN - highDouble: 1.5555
0.555d
is a double
value. It may be slightly larger than 0.555 or slightly smaller.
Rounding mode use for Round the Decimal Value.
You can use with.
double DecimalValue = 3.1452;
BigDecimal decimal = new BigDecimal(DecimalValue).setScale(2, RoundingMode.DOWN);
=>
RoundingMode.CEILING
Rounding mode to round towards positive infinity. For positive values this rounding mode behaves as UP, for negative values as DOWN. Rule: x.round() >= x
RoundingMode.DOWN
Rounding mode where the values are rounded towards zero. Rule: x.round().abs() <= x.abs()
RoundingMode.DOWN
Rounding mode to round towards negative infinity. For positive values this rounding mode behaves as DOWN, for negative values as UP. Rule: x.round() <= x
RoundingMode.HALF_DOWN
Rounding mode where values are rounded towards the nearest neighbor. Ties are broken by rounding down.
RoundingMode.HALF_EVEN
Rounding mode where values are rounded towards the nearest neighbor. Ties are broken by rounding to the even neighbor.
RoundingMode.HALF_UP
Rounding mode where values are rounded towards the nearest neighbor. Ties are broken by rounding up.
RoundingMode.UNNECESSARY
Rounding mode where the rounding operations throws an ArithmeticException
for the case that rounding is necessary, ie for the case that the value cannot be represented exactly.
RoundingMode.UP
Rounding mode where positive values are rounded towards positive infinity and negative values towards negative infinity. Rule: x.round().abs() >= x.abs()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.