6 Replies Latest reply: Nov 16, 2007 4:57 PM by 807603 RSS

    Determine number of decimal places? - BigDecimal.scale() doesn't make sense

    807603
      Hi all,
      I'm trying to determine the number of decimal places in a double. In my case, I want to make sure that the number has no more than 4 decimal places.


      I have tried something like

      double aDouble
      String str = Double.valueOf(aDouble).toString();
      str = str.substring(w1Str.indexOf(".") + 1);

      if(str.length() > 4)
      //throw error

      This approach works fine as long as the Double.toString() doesn't return a number in scientific notation.

      I've looked and haven't found a very good solution so far, so any suggestions would be welcome.

      I've tried to use BigDecimal.scale() to determine the number of decimal places in a number, but I have found for 0.35 that its scale is 53!! Granted, I haven't used BigDecimal very much, but per the BigDecimal API, it should return a scale() of 2. This is definitely the case for 0.25, but I don't understand why it is 53 for 0.35. Any explanation would be welcomed, but not necessary.

      Thanks,
      Jim
        • 1. Re: Determine number of decimal places? - BigDecimal.scale() doesn't make sense
          807603
          The big mistake the uninitiated make is confusing number display with number storage.
          If you are talking about restricting the display of the double to 4 decimal places then:
          http://java.sun.com/javase/6/docs/api/java/text/DecimalFormat.html
          • 2. Re: Determine number of decimal places? - BigDecimal.scale() doesn't make s
            807603
            I simply want to make sure the number entered by a user didn't have more than four decimal places. I think I see where you're coming from with regards to number storage.

            Jim
            • 3. Re: Determine number of decimal places? - BigDecimal.scale() doesn't make s
              807603
              the number entered by a user
              Your substring method would work fine.
              I dont see why youre working with a Double? The user had to enter the number as a String right?
              So unless you allow your users to use scientific notation... (hint: convert to double AFTER)

              Another (sloppy way) would be to shift the decimal, use floor(), and then shift back.
              • 4. Re: Determine number of decimal places? - BigDecimal.scale() doesn't make sense
                807603
                And I should have said this earlier, if youre using doubles then this requirement is ridiculous anyway. You could enter ".1234" and end up with ".123300000009" (not quite but something
                like that).

                Why? doubles are 64 bits with a potential for 1.8...e19 states and yet they attempt to represent
                values from 4.9...e-324d to 1.7...e+308d.
                • 5. Re: Determine number of decimal places? - BigDecimal.scale() doesn't make s
                  807603
                  Hi TuringPest,
                  Thanks for your quick responses and feedback. I'm using a Struts form bean and having Struts hand me a double to use in my code.

                  I ended up using the DecimalFormat class:

                  private boolean checkDecimalPlaces(double wf) {
                  DecimalFormat df = new DecimalFormat("#.######");
                  String format = df.format(wf);
                  format = format.substring(format.indexOf(".") + 1);

                  return format.length() > 4;
                  }

                  I used 6 #'s to be able to check for additional decimal places and then performed the check.

                  Thanks,
                  Jim
                  • 6. Re: Determine number of decimal places? - BigDecimal.scale() doesn't make s
                    807603
                    Jim,
                    Your code doesnt work.
                    if i enter .1234009999999 your test passes (because its truncating after 6 places).

                    Consider using my method:
                         return d > (Math.floor(d * 10000) / 10000);
                    Though with the finnickiness of floating point numbers...

                    This requirement with doubles is a little silly.
                    A more accurate approach might be a hybrid of both our ideas.

                    roughly:
                    return d > Double.parseDouble(("" + d).substring(0, decimalIndex + 5))
                    import java.text.*;
                    
                    public class NumberTester{
                    
                    public static void main(String[] args){
                    
                         System.out.println("test 1: " + NumberTester.test2(0.123400001));
                         System.out.println("test 2: " + NumberTester.test2(0.12345));
                    
                    }
                    
                    public static boolean test(double d){
                    
                         return d > (Math.floor(d * 10000) / 10000);
                    
                    }
                    
                    public static boolean test2(double wf) {
                    
                         DecimalFormat df = new DecimalFormat("#.######");
                         String format = df.format(wf);
                         System.out.println("format: " + format);
                         format = format.substring(format.indexOf(".") + 1);
                    
                         return format.length() > 4;
                    
                    }
                    
                    }