round BigDecimal to nearest 5 cents

I'd try multiplying by 20, rounding to the nearest integer, then dividing by 20. It's a hack, but should get you the right answer.


I wrote this in Java a few years ago: https://github.com/marcolopes/dma/blob/master/org.dma.java/src/org/dma/java/math/BusinessRules.java

/**
 * Rounds the number to the nearest<br>
 * Numbers can be with or without decimals<br>
 */
public static BigDecimal round(BigDecimal value, BigDecimal rounding, RoundingMode roundingMode){

    return rounding.signum()==0 ? value :
        (value.divide(rounding,0,roundingMode)).multiply(rounding);

}


/**
 * Rounds the number to the nearest<br>
 * Numbers can be with or without decimals<br>
 * Example: 5, 10 = 10
 *<p>
 * HALF_UP<br>
 * Rounding mode to round towards "nearest neighbor" unless
 * both neighbors are equidistant, in which case round up.
 * Behaves as for RoundingMode.UP if the discarded fraction is >= 0.5;
 * otherwise, behaves as for RoundingMode.DOWN.
 * Note that this is the rounding mode commonly taught at school.
 */
public static BigDecimal roundUp(BigDecimal value, BigDecimal rounding){

    return round(value, rounding, RoundingMode.HALF_UP);

}


/**
 * Rounds the number to the nearest<br>
 * Numbers can be with or without decimals<br>
 * Example: 5, 10 = 0
 *<p>
 * HALF_DOWN<br>
 * Rounding mode to round towards "nearest neighbor" unless
 * both neighbors are equidistant, in which case round down.
 * Behaves as for RoundingMode.UP if the discarded fraction is > 0.5;
 * otherwise, behaves as for RoundingMode.DOWN.
 */
public static BigDecimal roundDown(BigDecimal value, BigDecimal rounding){

    return round(value, rounding, RoundingMode.HALF_DOWN);

}

Using BigDecimal without any doubles (improved on the answer from marcolopes):

public static BigDecimal round(BigDecimal value, BigDecimal increment,
                               RoundingMode roundingMode) {
    if (increment.signum() == 0) {
        // 0 increment does not make much sense, but prevent division by 0
        return value;
    } else {
        BigDecimal divided = value.divide(increment, 0, roundingMode);
        BigDecimal result = divided.multiply(increment);
        return result;
    }
}

The rounding mode is e.g. RoundingMode.HALF_UP. For your examples, you actually want RoundingMode.UP (bd is a helper which just returns new BigDecimal(input)):

assertEquals(bd("1.05"), round(bd("1.03"), bd("0.05"), RoundingMode.UP));
assertEquals(bd("1.10"), round(bd("1.051"), bd("0.05"), RoundingMode.UP));
assertEquals(bd("1.05"), round(bd("1.05"), bd("0.05"), RoundingMode.UP));
assertEquals(bd("1.95"), round(bd("1.900001"), bd("0.05"), RoundingMode.UP));

Also note that there is a mistake in your last example (rounding 1.900001 to 1.10).