]> granicus.if.org Git - icu/commitdiff
ICU-20063 Make setSignificantDigitsUsed more friendly.
authorShane Carr <shane@unicode.org>
Tue, 18 Sep 2018 08:30:31 +0000 (01:30 -0700)
committerShane Carr <shane@unicode.org>
Thu, 27 Sep 2018 21:27:40 +0000 (14:27 -0700)
icu4c/source/i18n/decimfmt.cpp
icu4c/source/test/intltest/numfmtst.cpp
icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java

index a2638bb74298e3f15d4081f47ff921795884945c..832aece907c667081fdb3ec5ee760b4636016cf6 100644 (file)
@@ -1057,12 +1057,19 @@ UBool DecimalFormat::areSignificantDigitsUsed() const {
 
 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
     // These are the default values from the old implementation.
+    if (useSignificantDigits) {
+        if (fields->properties->minimumSignificantDigits != -1 ||
+            fields->properties->maximumSignificantDigits != -1) {
+            return;
+        }
+    } else {
+        if (fields->properties->minimumSignificantDigits == -1 &&
+            fields->properties->maximumSignificantDigits == -1) {
+            return;
+        }
+    }
     int32_t minSig = useSignificantDigits ? 1 : -1;
     int32_t maxSig = useSignificantDigits ? 6 : -1;
-    if (fields->properties->minimumSignificantDigits == minSig &&
-        fields->properties->maximumSignificantDigits == maxSig) {
-        return;
-    }
     fields->properties->minimumSignificantDigits = minSig;
     fields->properties->maximumSignificantDigits = maxSig;
     touchNoError();
index d28b94046144330c3bca28abf0ecb9949c35b0a5..db8d22728b18903342ae262a636bd1223a4ac482 100644 (file)
@@ -7367,6 +7367,35 @@ void NumberFormatTest::TestSignificantDigits(void) {
         }
         result.remove();
     }
+
+    // Test for ICU-20063
+    {
+        DecimalFormat df({"en-us", status}, status);
+        df.setSignificantDigitsUsed(TRUE);
+        expect(df, 9.87654321, u"9.87654");
+        df.setMaximumSignificantDigits(3);
+        expect(df, 9.87654321, u"9.88");
+        // setSignificantDigitsUsed with maxSig only
+        df.setSignificantDigitsUsed(TRUE);
+        expect(df, 9.87654321, u"9.88");
+        df.setMinimumSignificantDigits(2);
+        expect(df, 9, u"9.0");
+        // setSignificantDigitsUsed with both minSig and maxSig
+        df.setSignificantDigitsUsed(TRUE);
+        expect(df, 9, u"9.0");
+        // setSignificantDigitsUsed to false: should revert to fraction rounding
+        df.setSignificantDigitsUsed(FALSE);
+        expect(df, 9.87654321, u"9.876543");
+        expect(df, 9, u"9");
+        df.setSignificantDigitsUsed(TRUE);
+        df.setMinimumSignificantDigits(2);
+        expect(df, 9.87654321, u"9.87654");
+        expect(df, 9, u"9.0");
+        // setSignificantDigitsUsed with minSig only
+        df.setSignificantDigitsUsed(TRUE);
+        expect(df, 9.87654321, u"9.87654");
+        expect(df, 9, u"9.0");
+    }
 }
 
 void NumberFormatTest::TestShowZero() {
index ea2a1ca16e61084c0113ec05b4b29e61c7069543..f520e5ae5c5d140172d35fd475a293299ff6113c 100644 (file)
@@ -1560,14 +1560,22 @@ public class DecimalFormat extends NumberFormat {
    * @stable ICU 3.0
    */
   public synchronized void setSignificantDigitsUsed(boolean useSignificantDigits) {
+    int oldMinSig = properties.getMinimumSignificantDigits();
+    int oldMaxSig = properties.getMaximumSignificantDigits();
+    // These are the default values from the old implementation.
     if (useSignificantDigits) {
-      // These are the default values from the old implementation.
-      properties.setMinimumSignificantDigits(1);
-      properties.setMaximumSignificantDigits(6);
+      if (oldMinSig != -1 || oldMaxSig != -1) {
+        return;
+      }
     } else {
-      properties.setMinimumSignificantDigits(-1);
-      properties.setMaximumSignificantDigits(-1);
+      if (oldMinSig == -1 && oldMaxSig == -1) {
+        return;
+      }
     }
+    int minSig = useSignificantDigits ? 1 : -1;
+    int maxSig = useSignificantDigits ? 6 : -1;
+    properties.setMinimumSignificantDigits(minSig);
+    properties.setMaximumSignificantDigits(maxSig);
     refreshFormatter();
   }
 
index 008bfedb34ad30de89e0175dc341814f7857225a..5e67d35952d18ccc85aed78cb30ae243c22c719a 100644 (file)
@@ -3975,6 +3975,35 @@ public class NumberFormatTest extends TestFmwk {
         for (int i = 0; i < input.length; i++) {
             assertEquals("TestSignificantDigits", expected[i], numberFormat.format(input[i]));
         }
+
+        // Test for ICU-20063
+        {
+            DecimalFormat df = new DecimalFormat("0.######", DecimalFormatSymbols.getInstance(ULocale.US));
+            df.setSignificantDigitsUsed(true);
+            expect(df, 9.87654321, "9.87654");
+            df.setMaximumSignificantDigits(3);
+            expect(df, 9.87654321, "9.88");
+            // setSignificantDigitsUsed with maxSig only
+            df.setSignificantDigitsUsed(true);
+            expect(df, 9.87654321, "9.88");
+            df.setMinimumSignificantDigits(2);
+            expect(df, 9, "9.0");
+            // setSignificantDigitsUsed with both minSig and maxSig
+            df.setSignificantDigitsUsed(true);
+            expect(df, 9, "9.0");
+            // setSignificantDigitsUsed to false: should revert to fraction rounding
+            df.setSignificantDigitsUsed(false);
+            expect(df, 9.87654321, "9.876543");
+            expect(df, 9, "9");
+            df.setSignificantDigitsUsed(true);
+            df.setMinimumSignificantDigits(2);
+            expect(df, 9.87654321, "9.87654");
+            expect(df, 9, "9.0");
+            // setSignificantDigitsUsed with minSig only
+            df.setSignificantDigitsUsed(true);
+            expect(df, 9.87654321, "9.87654");
+            expect(df, 9, "9.0");
+        }
     }
 
     @Test
@@ -4501,7 +4530,7 @@ public class NumberFormatTest extends TestFmwk {
     private void CompareAttributedCharacterFormatOutput(AttributedCharacterIterator iterator,
         List<FieldContainer> expected, String formattedOutput) {
 
-        List<FieldContainer> result = new ArrayList<FieldContainer>();
+        List<FieldContainer> result = new ArrayList<>();
         while (iterator.getIndex() != iterator.getEndIndex()) {
             int start = iterator.getRunStart();
             int end = iterator.getRunLimit();
@@ -4540,7 +4569,7 @@ public class NumberFormatTest extends TestFmwk {
     @Test
     public void TestNPEIssue11914() {
         // First test: Double value with grouping separators.
-        List<FieldContainer> v1 = new ArrayList<FieldContainer>(7);
+        List<FieldContainer> v1 = new ArrayList<>(7);
         v1.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER));
         v1.add(new FieldContainer(3, 4, NumberFormat.Field.GROUPING_SEPARATOR));
         v1.add(new FieldContainer(4, 7, NumberFormat.Field.INTEGER));
@@ -4560,7 +4589,7 @@ public class NumberFormatTest extends TestFmwk {
         CompareAttributedCharacterFormatOutput(iterator, v1, numFmtted);
 
         // Second test: Double with scientific notation formatting.
-        List<FieldContainer> v2 = new ArrayList<FieldContainer>(7);
+        List<FieldContainer> v2 = new ArrayList<>(7);
         v2.add(new FieldContainer(0, 1, NumberFormat.Field.INTEGER));
         v2.add(new FieldContainer(1, 2, NumberFormat.Field.DECIMAL_SEPARATOR));
         v2.add(new FieldContainer(2, 5, NumberFormat.Field.FRACTION));
@@ -4574,7 +4603,7 @@ public class NumberFormatTest extends TestFmwk {
         CompareAttributedCharacterFormatOutput(iterator, v2, numFmtted);
 
         // Third test. BigInteger with grouping separators.
-        List<FieldContainer> v3 = new ArrayList<FieldContainer>(7);
+        List<FieldContainer> v3 = new ArrayList<>(7);
         v3.add(new FieldContainer(0, 1, NumberFormat.Field.SIGN));
         v3.add(new FieldContainer(1, 2, NumberFormat.Field.INTEGER));
         v3.add(new FieldContainer(2, 3, NumberFormat.Field.GROUPING_SEPARATOR));
@@ -4596,7 +4625,7 @@ public class NumberFormatTest extends TestFmwk {
         CompareAttributedCharacterFormatOutput(iterator, v3, fmtNumberBigInt);
 
         // Fourth test: BigDecimal with exponential formatting.
-        List<FieldContainer> v4 = new ArrayList<FieldContainer>(7);
+        List<FieldContainer> v4 = new ArrayList<>(7);
         v4.add(new FieldContainer(0, 1, NumberFormat.Field.SIGN));
         v4.add(new FieldContainer(1, 2, NumberFormat.Field.INTEGER));
         v4.add(new FieldContainer(2, 3, NumberFormat.Field.DECIMAL_SEPARATOR));