Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine Number of Decimal Place using BigDecimal

Tags:

java

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.

like image 996
Cheok Yan Cheng Avatar asked Feb 19 '10 12:02

Cheok Yan Cheng


People also ask

How do I find the number of decimal places in BigDecimal?

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.

Does BigDecimal have decimal places?

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.

How do I restrict to 2 decimal places in Java?

1. DecimalFormat(“0.00”) We can use DecimalFormat("0.00") to ensure the number always round to 2 decimal places.

How do you find the whole number in BigDecimal?

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.


4 Answers

Combining Turismo, Robert and user1777653's answers, we've got:

int getNumberOfDecimalPlaces(BigDecimal bigDecimal) {     return Math.max(0, bigDecimal.stripTrailingZeros().scale()); } 
  • stripTrailingZeros() ensures that trailing zeros are not counted (e.g. 1.0 has 0 decimal places).
  • scale() is more efficient than String.indexOf().
  • A negative scale() represents zero decimal places.

There you have it, the best of both worlds.

like image 127
Gili Avatar answered Sep 21 '22 05:09

Gili


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.

like image 33
Robert Atkins Avatar answered Sep 17 '22 05:09

Robert Atkins


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;
  }
like image 42
Axel Podehl Avatar answered Sep 18 '22 05:09

Axel Podehl


That should do it

int getNumberOfDecimalPlace(BigDecimal number) {
    int scale = number.stripTrailingZeros().scale();
    return scale > 0 ? scale : 0;
}
like image 28
user1777653 Avatar answered Sep 20 '22 05:09

user1777653