Java Bigdecimal: Round to the Nearest Whole Value

Java BigDecimal: Round to the nearest whole value

You can use setScale() to reduce the number of fractional digits to zero. Assuming value holds the value to be rounded:

BigDecimal scaled = value.setScale(0, RoundingMode.HALF_UP);
System.out.println(value + " -> " + scaled);

Using round() is a bit more involved as it requires you to specify the number of digits to be retained. In your examples this would be 3, but this is not valid for all values:

BigDecimal rounded = value.round(new MathContext(3, RoundingMode.HALF_UP));
System.out.println(value + " -> " + rounded);

(Note that BigDecimal objects are immutable; both setScale and round will return a new object.)

Java BigDecimal.round()

Also you can update your code to it:

BigDecimal newValue = oldValue.round(new MathContext(oldValue.precision() - 3,
RoundingMode.CEILING));

Round up BigDecimal to Integer value

setScale returns a new BigDecimal with the result, it doesn't change the instance you call it on. So assign the return value back to value:

value = value.setScale(0, RoundingMode.UP);

Live Example

I also changed it to RoundingMode.UP because you said you always wanted to round up. But depending on your needs, you might want RoundingMode.CEILING instead; it depends on what you want -451.2 to become (-452 [UP] or -451 [CEILING]). See RoundingMode for more.

Rounding Bigdecimal values with 2 Decimal Places

I think that the RoundingMode you are looking for is ROUND_HALF_EVEN. From the javadoc:

Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor. Behaves as for ROUND_HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for ROUND_HALF_DOWN if it's even. Note that this is the rounding mode that minimizes cumulative error when applied repeatedly over a sequence of calculations.

Here is a quick test case:

BigDecimal a = new BigDecimal("10.12345");
BigDecimal b = new BigDecimal("10.12556");

a = a.setScale(2, BigDecimal.ROUND_HALF_EVEN);
b = b.setScale(2, BigDecimal.ROUND_HALF_EVEN);

System.out.println(a);
System.out.println(b);

Correctly prints:

10.12
10.13

UPDATE:

setScale(int, int) has not been recommended since Java 1.5, when enums were first introduced, and was finally deprecated in Java 9. You should now use setScale(int, RoundingMode) e.g:

setScale(2, RoundingMode.HALF_EVEN)

BigDecimal in Java: How to round to 10?

You are missing that the MathContext object with which you are performing the rounding specifies the precision of the rounded result (== number of significant digits), not the scale (related to the place value of the least-significant digit). More generally, BigDecimal.round() is all about managing the precision of your numbers, which is not what you're after.

You can round a BigDecimal to the nearest multiple of any given power of 10 by setting its scale. To round to the nearest multiple of 10 itself, that would be:

number = number.setScale(-1, RoundingMode.HALF_UP));

Note that if the initial scale is less than -1, then this results in an increase in the precision of the number (by addition of significant trailing zeroes). If you don't want that, then test the scale (BigSecimal.scale()) to determine whether to round.

Is this the correct behavior for rounding with BigDecimals?

HALF_DOWN only rounds down when the actual value is exactly half-way between the two possible rounded values. I.e. 5.46500 -> 5.46. On the other hand 5.4650000001 -> 5.47 because that's nearer to 5.47 than 5.46.

Perhaps what you're looking for is RoundingMode.DOWN, which always rounds down.

Round to nearest value using HALF_UP

You expect to round up the number always, in your case use RoundingMode.UP

HALF_UP will round only from .5 up

Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.

Table showing the results of these rounding operations:

Input Number  UP  DOWN    CEILING FLOOR   HALF_UP HALF_DOWN   HALF_EVEN   UNNECESSARY
5.5 6 5 6 5 6 5 6 throw ArithmeticException
2.5 3 2 3 2 3 2 2 throw ArithmeticException
1.6 2 1 2 1 2 2 2 throw ArithmeticException
1.1 2 1 2 1 1 1 1 throw ArithmeticException

BigDecimal not retaining rounded value when converting to/from float

I've decided to modify my program to use BigDecimal as the base type for my property price in my object instead of type float. Although tricky at first it is definitely the cleaner solution in the long run.

public class Order {
// float price; // old type
BigDecimal price; // new type
}

BigDecimal round to 0 or 5

You can multiply by 2, then round to the nearest 10, then divide by 2. The precision is 2 for these BigDecimals; it may need to be different for BigDecimals of different scale.

BigDecimal[] bds = {new BigDecimal("64.99"), new BigDecimal("65.01")};
BigDecimal two = new BigDecimal("2");
MathContext mcUp = new MathContext(2, RoundingMode.UP);
MathContext mcDown = new MathContext(2, RoundingMode.DOWN);
NumberFormat currency = NumberFormat.getCurrencyInstance();
for (BigDecimal bd : bds)
{
System.out.println("Test: " + bd);
BigDecimal roundUp5 = bd.multiply(two).round(mcUp).divide(two);
System.out.println("Round up: " + currency.format(roundUp5));
BigDecimal roundDown5 = bd.multiply(two).round(mcDown).divide(two);
System.out.println("Round down: " + currency.format(roundDown5));
}

Output:

Test: 64.99
Round up: $65.00
Round down: $60.00
Test: 65.01
Round up: $70.00
Round down: $65.00


Related Topics



Leave a reply



Submit