Reputation: 75
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
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
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
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
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