fix BigDecimal.compareTo and precision for leading zeros

http://code.google.com/p/google-web-toolkit/issues/detail?id=7834

Fixes issue 7834
Based on a patch by jat@jaet.org

Change-Id: I9874897f54a9eb6ce15f5b7b6295613800a25b72
Review-Link: https://gwt-review.googlesource.com/#/c/1660/


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11494 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/super/com/google/gwt/emul/java/math/BigDecimal.java b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
index 7cc988b..ffbdfb7 100644
--- a/user/super/com/google/gwt/emul/java/math/BigDecimal.java
+++ b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
@@ -2615,18 +2615,10 @@
         throw new NumberFormatException("For input string: \"" + val + "\"");
       }
     }
-    int counter = 0;
-    boolean wasNonZero = false;
     // Accumulating all digits until a possible decimal point
-    for (; (offset < last) && (val.charAt(offset) != '.')
-        && (val.charAt(offset) != 'e') && (val.charAt(offset) != 'E'); offset++) {
-      if (!wasNonZero) {
-        if (val.charAt(offset) == '0') {
-          counter++;
-        } else {
-          wasNonZero = true;
-        }
-      }
+    while ((offset < last) && (val.charAt(offset) != '.')
+        && (val.charAt(offset) != 'e') && (val.charAt(offset) != 'E')) {
+      offset++;
     }
     unscaledBuffer.append(val, begin, offset);
     // A decimal point was found
@@ -2634,15 +2626,9 @@
       offset++;
       // Accumulating all digits until a possible exponent
       begin = offset;
-      for (; (offset < last) && (val.charAt(offset) != 'e')
-          && (val.charAt(offset) != 'E'); offset++) {
-        if (!wasNonZero) {
-          if (val.charAt(offset) == '0') {
-            counter++;
-          } else {
-            wasNonZero = true;
-          }
-        }
+      while ((offset < last) && (val.charAt(offset) != 'e')
+          && (val.charAt(offset) != 'E')) {
+        offset++;
       }
       scale = offset - begin;
       unscaledBuffer.append(val, begin, offset);
@@ -2681,7 +2667,7 @@
     } else {
       setUnscaledValue(new BigInteger(unscaled));
     }
-    precision = unscaledBuffer.length() - counter;
+    precision = unscaledBuffer.length();
     // Don't count leading zeros in the precision
     for (int i = 0; i < unscaledBuffer.length(); ++i) {
       char ch = unscaledBuffer.charAt(i);
@@ -2690,6 +2676,10 @@
       }
       --precision;
     }
+    // The precision of a zero value is 1
+    if (precision == 0) {
+      precision = 1;
+    }
   }
 
   /**
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java
index 794309e..474ce3a 100644
--- a/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalCompareTest.java
@@ -248,6 +248,23 @@
   }
 
   /**
+   * Test identical fraction values with different scales.
+   * http://code.google.com/p/google-web-toolkit/issues/detail?id=7834
+   */
+  public void testFractionScale() {
+    BigDecimal a = new BigDecimal("0.02");
+    BigDecimal b = new BigDecimal("0.02000");
+    assertEquals(0, a.compareTo(b));
+
+    BigDecimal a1 = new BigDecimal("0.029900000000000003");
+    BigDecimal a2 = new BigDecimal("0.0001");
+    a = a1.add(a2);
+    // a is 0.030000000000000003 (0.029900000000000003 + 0.0001)
+    b = new BigDecimal("0.03990");
+    assertEquals(-1, a.compareTo(b));
+  }
+
+  /**
    * hashCode() for equal BigDecimals.
    */
   public void testHashCodeEqual() {
diff --git a/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java b/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java
index aa5765c..15bdee8 100644
--- a/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java
+++ b/user/test/com/google/gwt/emultest/java/math/BigDecimalConstructorsTest.java
@@ -687,11 +687,19 @@
   }
 
   /**
-   * Test second failing example in gwt-java-math issue 4.
+   * Test second failing example in gwt-java-math issue 4 and variations
+   * to validate that precision is calculated correctly when leading zeros
+   * and minus signs are present.
    */
   public void testConstrStringWithLeadingZeros() {
-    BigDecimal value = new BigDecimal("-000.1");
-    assertEquals("bad precision", 1, value.precision());
+    assertEquals("bad precision", 1, new BigDecimal("-000.1").precision());
+    assertEquals("bad precision", 4, new BigDecimal("001234").precision());
+    assertEquals("bad precision", 4, new BigDecimal("-5555").precision());
+    assertEquals("bad precision", 1, new BigDecimal("0").precision());
+    assertEquals("bad precision", 1, new BigDecimal("-0").precision());
+    assertEquals("bad precision", 4, new BigDecimal("001234e3").precision());
+    assertEquals("bad precision", 5, new BigDecimal("00056789e+17").precision());
+    assertEquals("bad precision", 6, new BigDecimal("0900000e-42").precision());
   }
 
   /**