I was interested to have the following getNumberOfDecimalPlace
function:
System.out.println("0 = " + Utils.getNumberOfDecimalPlace(0)); // 0
System.out.println("1.0 = " + Utils.getNumberOfDecimalPlace(1.0)); // 0
System.out.println("1.01 = " + Utils.getNumberOfDecimalPlace(1.01)); // 2
System.out.println("1.012 = " + Utils.getNumberOfDecimalPlace(1.012)); // 3
System.out.println("0.01 = " + Utils.getNumberOfDecimalPlace(0.01)); // 2
System.out.println("0.012 = " + Utils.getNumberOfDecimalPlace(0.012)); // 3
May I know how can I implement getNumberOfDecimalPlace
, by using BigDecimal
?
The following code doesn't work as expected:
public static int getNumberOfDecimalPlace(double value) {
final BigDecimal bigDecimal = new BigDecimal("" + value);
final String s = bigDecimal.toPlainString();
System.out.println(s);
final int index = s.indexOf('.');
if (index < 0) {
return 0;
}
return s.length() - 1 - index;
}
The following get printed :
0.0
0 = 1
1.0
1.0 = 1
1.01
1.01 = 2
1.012
1.012 = 3
0.01
0.01 = 2
0.012
0.012 = 3
However, for case 0, 1.0, it doesn't work well. I expect, "0" as result. But they turned out to be "0.0" and "1.0". This will return "1" as result.
math. BigDecimal. scale() is an inbuilt method in java that returns the scale of this BigDecimal. For zero or positive value, the scale is the number of digits to the right of the decimal point.
Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point.
1. DecimalFormat(“0.00”) We can use DecimalFormat("0.00") to ensure the number always round to 2 decimal places.
intValue() is an in-built function which converts this BigDecimal to an integer value. This function discards any fractional part of this BigDecimal. If the result of the conversion is too big to be represented as an integer value, the function returns only the lower-order 32 bits.
Combining Turismo, Robert and user1777653's answers, we've got:
int getNumberOfDecimalPlaces(BigDecimal bigDecimal) { return Math.max(0, bigDecimal.stripTrailingZeros().scale()); }
1.0
has 0 decimal places).scale()
is more efficient than String.indexOf()
.scale()
represents zero decimal places.There you have it, the best of both worlds.
This code:
int getNumberOfDecimalPlaces(BigDecimal bigDecimal) { String string = bigDecimal.stripTrailingZeros().toPlainString(); int index = string.indexOf("."); return index < 0 ? 0 : string.length() - index - 1; }
... passes these tests:
assertThat(getNumberOfDecimalPlaces(new BigDecimal("0.001")), equalTo(3)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("0.01")), equalTo(2)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("0.1")), equalTo(1)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("1.000")), equalTo(0)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("1.00")), equalTo(0)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("1.0")), equalTo(0)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("1")), equalTo(0)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("10")), equalTo(0)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("10.1")), equalTo(1)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("10.01")), equalTo(2)); assertThat(getNumberOfDecimalPlaces(new BigDecimal("10.001")), equalTo(3));
... if that is indeed what you want. The other replies are correct, you have to use BigDecimal all the way through for this rather than double/float.
Without having to convert to String, it should be more efficient to use the scale directly:
private int getNumberOfDecimalPlaces(BigDecimal bigDecimal)
{
int scale = bigDecimal.stripTrailingZeros().scale();
return scale>0?scale:0;
}
That should do it
int getNumberOfDecimalPlace(BigDecimal number) {
int scale = number.stripTrailingZeros().scale();
return scale > 0 ? scale : 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With