Search code examples
javabigdecimal

Java BigDecimal: Rounding off to client preferred digits and increment


I have a requirement to round certain values according to client preference. Clients can customize the number of digits and round off values like below.

NumOfDigits | RoundOff | InputValue || ExpectedOutput
    0.01    | 2        | 43.0       || 43.0
    0.01    | 2        | 43.1       || 43.1
    0.01    | 2        | 43.11      || 43.11
    0.01    | 2        | 43.11234   || 43.11

    0.1     | 1        | 43.0       || 43.0
    0.1     | 1        | 43.1       || 43.1
    0.1     | 1        | 43.12      || 43.1
    0.1     | 1        | 43.1234    || 43.1

    0.2     | 1        | 43.0       || 43.0
    0.2     | 1        | 43.1       || 43.0
    0.2     | 1        | 43.2       || 43.2
    0.2     | 1        | 43.3       || 43.2
    0.2     | 1        | 43.11      || 43.0

    0.3     | 1        | 43.0       || 43.0
    0.3     | 1        | 43.1       || 43.0
    0.3     | 1        | 43.2       || 43.0
    0.3     | 1        | 43.3       || 43.3
    0.3     | 1        | 43.11      || 43.0

    0.25    | 2        | 33.0       || 33.0
    0.25    | 2        | 33.3       || 33.25
    0.25    | 2        | 33.7       || 33.50
    0.25    | 2        | 33.9       || 33.75
    0.25    | 2        | 33.33      || 33.25
    0.25    | 2        | 33.71      || 33.50
    0.25    | 2        | 33.91      || 33.75
    0.25    | 2        | 33.12345   || 33.25

I was able to restrict the number of digits with the below code. However, I'm not able to find a solution for rounding off as per above logic.

    BigDecimal incrementedValue = BigDecimal.valueOf(inputValue).setScale(numOfDigits, ROUND_DOWN);

Solution

  • According to Wikipedia (http://en.wikipedia.org/wiki/Rounding#Rounding_to_a_specified_increment), rounding a number x to a multiple of some increment m requires the following procedure:

    Rounded value z = round(x, m) = round(x / m) * m

    In your case, you want to always round down. This is achieved by using floor instead of round. Translated into Java, your program will look something like this.

    // ex. input = 33.91, increment = 0.25 -> 33.75
    public double round(double input, double increment) {
         return Math.floor(input / increment) * increment;
    }