Raj
Raj

Reputation: 75

Print rounded digits without extra zeros

I'm trying to round using BigDecimal.ROUND_HALF_UP but am not getting expected results. This code:

String desVal="21.999";  
BigDecimal decTest=new BigDecimal(
    String.valueOf(desVal)
)
.setScale(
    Integer.parseInt(decimalPlaces), BigDecimal.ROUND_DOWN
);     
System.out.println(decTest); 

Gives the following results:

decimalPlaces=1 it is displaying 21.9 //correct 
decimalPlaces=2 displaying 21.99 //correct 
decimalplaces=3 displaying 21.999 //correct 
decimalplaces=4 displaying 21.9990 //incorrect 

I want to get the following:

decimalPlaces=1 should display 21.9      
decimalPlaces=2 should display 21.99 
decimalplaces=3 should display 21.999 
decimalplaces=4 should display 21.999 

Is there a way to do this with standard Java (ie no external libraries)?

Upvotes: 1

Views: 176

Answers (4)

Joeri Hendrickx
Joeri Hendrickx

Reputation: 17435

If you want to print trailing zeroes, but not all of them, you will need a DecimalFormat. The trick is that in your case, you need to build the Format String depending on the number of decimals in the original input String.

    int decimalPlaces = 10;
    String desVal="21.99900";  

    // find the decimal part of the input (if there is any)
    String decimalPart = desVal.contains(".")?desVal.split(Pattern.quote("."))[1]:"";

    // build our format string, with the expected number of digits after the point
    StringBuilder format = new StringBuilder("#");
            if (decimalPlaces>0) format.append(".");
    for(int i=0; i<decimalPlaces; i++){
        // if we've passed the original decimal part, we don't want trailing zeroes
        format.append(i>=decimalPart.length()?"#":"0");
    }

    // do the rounding
    BigDecimal decTest=new BigDecimal(
        String.valueOf(desVal)
    )
    .setScale(
        decimalPlaces, BigDecimal.ROUND_DOWN
    );   

    NumberFormat nf = new DecimalFormat(format.toString());
    System.out.println(nf.format(decTest));

Upvotes: 0

Mena
Mena

Reputation: 48404

Use BigDecimal#stripTrailingZeros():

String[] decimalPlaces = new String[] {"2", "2", "3", "4", "4"};
String[] desVal = new String[] {"20", "21.9", "21.90", "21.99999", "21.99990"};

for (int i = 0; i < desVal.length; i++) {
    BigDecimal decTest = new BigDecimal(desVal[i]);

    if (decTest.scale() > 0 && !desVal[i].endsWith("0") &&  !(Integer.parseInt(decimalPlaces[i]) > decTest.scale())) {
        decTest = decTest.setScale(Integer.parseInt(decimalPlaces[i]),
                BigDecimal.ROUND_DOWN).stripTrailingZeros();
    }
    System.out.println(decTest);
}

Output:

20
21.9
21.90
21.9999
21.99990

Upvotes: 3

chetan
chetan

Reputation: 2886

You can use java.text.NumberFormat

NumberFormat nf = NumberFormat.getInstance();

System.out.println(nf.format(decTest));

If you want to preserve original scale, then

String desVal="21.99901";  
BigDecimal decTest=new BigDecimal(String.valueOf(desVal)); 
int origScale = decTest.scale();
decTest = decTest.setScale(4, BigDecimal.ROUND_DOWN);
System.out.println(String.format("%."+origScale+"f", decTest));

Upvotes: 0

Ahmed KRAIEM
Ahmed KRAIEM

Reputation: 10427

int decPlaces = Math.min(Integer.parseInt(decimalPlaces), 
                         desVal.length() - desVal.indexOf(".") + 1);
BigDecimal decTest=
      new BigDecimal(String.valueOf(desVal)).
             setScale(decPlaces, BigDecimal.ROUND_DOWN);

Upvotes: 0

Related Questions