Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5073448

java.text.DigitList..getBigDecimal() should use BigDecimal.scaleByPowerOfTen()

XMLWordPrintable

    • mustang
    • x86
    • linux

      Name: jl125535 Date: 07/13/2004


      FULL PRODUCT VERSION :
      java version "1.5.0-beta2"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b51)
      Java HotSpot(TM) Client VM (build 1.5.0-beta2-b51, mixed mode, sharing)


      EXTRA RELEVANT SYSTEM CONFIGURATION :
      not relevant

      A DESCRIPTION OF THE PROBLEM :
      Method getBigDecimal() in class java.text.DigitList can be optimized. Since Tiger, BigDecimal has constructors that accept char[] arguments, and the new method scaleByPowerOfTen() method.
      Instead of

      <code>
              StringBuffer temp = new StringBuffer(count + 12);
              temp.append('.');
              temp.append(digits, 0, count);
              temp.append('E');
              temp.append(decimalAt);
              return new BigDecimal(temp.toString());
      </code>

      use

      <code>
              return new BigDecimal(digits, 0, count).scaleByPowerOfTen(decimalAt - count);
      </code>

      As a result, DecimalFormat will take about 60% time compared to the current implementation.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test case. The output will show how long parsing takes. Note that the creation of the BigDecimal the old way takes about 85% of the processing time.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Parsing 12345 for 1000000 times took 1250ms.
      Using char[] constructor for 1000000 times took 818ms.
      Using StringBuffer for 1000000 times took 1760ms.

      ACTUAL -
      Parsing 12345 for 1000000 times took 2108ms.
      Using char[] constructor for 1000000 times took 818ms.
      Using StringBuffer for 1000000 times took 1760ms.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.*;

      import java.text.DecimalFormat;
      import java.math.BigDecimal;

      public class Test {
          
          public static void main(String[] args) {
              // TODO code application logic here
              String value = "12345";
              char[] digits = value.toCharArray();
              int decimalAt = 5;
              int count = digits.length;
              
              int loopCount = 1000000;
              DecimalFormat fmt = new DecimalFormat();
              fmt.setParseBigDecimal(true);
              try {
                  BigDecimal d = (BigDecimal) fmt.parse(value);
                  long startTime, endTime;
                  
                  /** The normal usage */
                  startTime = System.currentTimeMillis();
                  for (int i = 0; i < loopCount; ++i ) {
                      d = (BigDecimal) fmt.parse(value);
                  }
                  endTime = System.currentTimeMillis();
                  System.out.println("Parsing " + value + " for " + loopCount
                       + " times took " + (endTime - startTime) + "ms.");
                  
                  /** The fast way */
                  startTime = System.currentTimeMillis();
                  for (int i = 0; i < loopCount; ++i ) {
                      d = new BigDecimal(digits, 0, count)
                          .scaleByPowerOfTen(decimalAt - count);
                  }
                  endTime = System.currentTimeMillis();
                  System.out.println("Using char[] constructor for " + loopCount
                      + " times took " + (endTime - startTime) + "ms.");

                  /** The slow way */
                  startTime = System.currentTimeMillis();
                  for (int i = 0; i < loopCount; ++i ) {
                      StringBuffer temp = new StringBuffer(count + 12);
                      temp.append('.');
                      temp.append(digits, 0, count);
                      temp.append('E');
                      temp.append(decimalAt);
                      d = new BigDecimal(temp.toString());
                  }
                  endTime = System.currentTimeMillis();
                  System.out.println("Using StringBuffer for " + loopCount
                      + " times took " + (endTime - startTime) + "ms.");
              } catch (java.text.ParseException e) {
                  e.printStackTrace();
              }
          }
      }

      ---------- END SOURCE ----------
      (Incident Review ID: 285234)
      ======================================================================
      ###@###.### 10/4/04 03:45 GMT

            peytoia Yuka Kamiya (Inactive)
            jleesunw Jon Lee (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: