Removing trailing zeros from BigDecimal in Java
I need to remove trailing zeros from BigDecimal
along with RoundingMode.HALF_UP
. For instance,
Value Output
15.3456 <=> 15.35
15.999 <=> 16 //No trailing zeros.
15.99 <=> 15.99
15.0051 <=> 15.01
15.0001 <=> 15 //No trailing zeros.
15.000000<=> 15 //No trailing zeros.
15.00 <=> 15 //No trailing zeros.
stripTrailingZeros()
works but it returns scientific notations in situations like,
new BigDecimal("600.0").setScale(2, RoundingMode.HALF_UP).stripTrailingZeros();
In this case, it returns 6E+2
. I need this in a custom converter in JSF where it might be ugly for end users. So, what is the proper way of doing this?
Solution 1:
Use toPlainString()
BigDecimal d = new BigDecimal("600.0").setScale(2, RoundingMode.HALF_UP).stripTrailingZeros();
System.out.println(d.toPlainString()); // Printed 600 for me
I'm not into JSF (yet), but converter might look like this:
@FacesConverter("bigDecimalPlainDisplay")
public class BigDecimalDisplayConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
throw new BigDecimal(value);
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
BigDecimal bd = (BigDecimal)value;
return bd.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
}
}
and then in xhtml:
<h:inputText id="bigDecimalView" value="#{bigDecimalObject}"
size="20" required="true" label="Value">
<f:converter converterId="bigDecimalPlainDisplay" />
</h:inputText>
Solution 2:
Note that stripTrailingZeros()
doesn't do very well either.
On this:
val = new BigDecimal("0.0000").stripTrailingZeros();
System.out.println(val + ": plain=" + val.toPlainString());
val = new BigDecimal("40.0000").stripTrailingZeros();
System.out.println(val + ": plain=" + val.toPlainString());
val = new BigDecimal("40.50000").stripTrailingZeros();
System.out.println(val + ": plain=" + val.toPlainString());
Output (Java 7):
0.0000: plain=0.0000
4E+1: plain=40
40.5: plain=40.5
Output (Java 8):
0: plain=0
4E+1: plain=40
40.5: plain=40.5
The 0.0000
issue in Java 7 is fixed in Java 8 by the following java fix.
Solution 3:
If you want to do this at your BigDecimal object and not convert it into a String with a formatter you can do it on Java 8 with 2 steps:
- stripTrailingZeros()
- if scale < 0 setScale to 0 if don't like esponential/scientific notation
You can try this snippet to better understand the behaviour
BigDecimal bigDecimal = BigDecimal.valueOf(Double.parseDouble("50"));
bigDecimal = bigDecimal.setScale(2);
bigDecimal = bigDecimal.stripTrailingZeros();
if (bigDecimal.scale()<0)
bigDecimal= bigDecimal.setScale(0);
System.out.println(bigDecimal);//50
bigDecimal = BigDecimal.valueOf(Double.parseDouble("50.20"));
bigDecimal = bigDecimal.setScale(2);
bigDecimal = bigDecimal.stripTrailingZeros();
if (bigDecimal.scale()<0)
bigDecimal= bigDecimal.setScale(0);
System.out.println(bigDecimal);//50.2
bigDecimal = BigDecimal.valueOf(Double.parseDouble("50"));
bigDecimal = bigDecimal.setScale(2);
bigDecimal = bigDecimal.stripTrailingZeros();
System.out.println(bigDecimal);//5E+1
bigDecimal = BigDecimal.valueOf(Double.parseDouble("50.20"));
bigDecimal = bigDecimal.setScale(2);
bigDecimal = bigDecimal.stripTrailingZeros();
System.out.println(bigDecimal);//50.2