Search code examples
javabigdecimal

Java BigDecimal: How to set scale only if it's greater than certain precision point?


I have a use case where I want to set scale only if the number's precision is bigger than certain number. In other words, I want to set scale to 4 if the precision is 5 but leave the number as it is if precision is less than 4.

This is the expected result I am expecting ->

123.123 => 123.123 -> leave the number as it is because precision is less than 4.

123.123456 => 123.1235 -> scale is set, and rounded up.

123 => 123 -> leave the number as it is, since precision is less than 4.

0.1234445 => 0.1234 -> scale is set, and rounded down.

How can I achieve this result using Java's BigDecimal?


Solution

  • It seems like the question you really are asking is "How do I truncate the decimal portion of a BigDecimal so that it has at most 4 numbers to the right of the decimal point?"

    First, I think you should ensure you understand what scale and precision mean with regards to a BigDecimal.

    If you run this small program:

    public static void main(String[] args) {
        List<BigDecimal> decimals = new LinkedList<>();
        decimals.add( new BigDecimal(".123456"));
        decimals.add( new BigDecimal("1.23456"));
        decimals.add( new BigDecimal("12.3456"));
        decimals.add( new BigDecimal("123.456"));
        decimals.add( new BigDecimal("1234.56"));
        decimals.add( new BigDecimal("12345.6"));
        decimals.add( new BigDecimal("123456"));
    
        for(BigDecimal bd : decimals){
            System.out.println(bd.toPlainString() + ". scale = " + bd.scale() + ", precision = " + bd.precision());
        }
    }
    

    You'll see the following output:

    0.123456. scale = 6, precision = 6 
    1.23456. scale = 5, precision = 6
    12.3456. scale = 4, precision = 6
    123.456. scale = 3, precision = 6
    1234.56. scale = 2, precision = 6
    12345.6. scale = 1, precision = 6
    123456. scale = 0, precision = 6
    

    You should now see that what you want to do is query and then adjust the scale of the number.

    static BigDecimal doIt(BigDecimal input){
        if(input.scale() > 4){
            return input.setScale(4, RoundingMode.HALF_DOWN);
        }
        else{
            return input;
        }
    }
    

    A little test program shows the output is what you requested:

    public static void main(String[] args) {
        List<BigDecimal> decimals = new LinkedList<>();
        decimals.add(new BigDecimal("123.123"));
        decimals.add(new BigDecimal("123.123456"));
        decimals.add(new BigDecimal("123"));
        decimals.add(new BigDecimal("0.1234445"));
    
    
        for (BigDecimal bd : decimals) {
            System.out.println(bd.toPlainString() + " ---> " + doIt(bd));
        }
    }
    

    Output

    123.123 ---> 123.123
    123.123456 ---> 123.1235
    123 ---> 123
    0.1234445 ---> 0.1234