]> granicus.if.org Git - icu/commitdiff
ICU-20417 Adding parity between NoUnit and MeasureUnit Percent for short forms.
authorShane Carr <shane@unicode.org>
Fri, 15 Feb 2019 04:20:20 +0000 (20:20 -0800)
committerShane F. Carr <shane@unicode.org>
Thu, 21 Feb 2019 08:28:51 +0000 (02:28 -0600)
- Use Percent pattern for MeasureUnit Percent instead of the short or narrow form pattern from CLDR.

icu4c/source/i18n/number_formatimpl.cpp
icu4c/source/test/intltest/numbertest.h
icu4c/source/test/intltest/numbertest_api.cpp
icu4c/source/test/intltest/numbertest_decimalquantity.cpp
icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/ExhaustiveNumberTest.java

index a7f162ecc633cf53d07b604843d7a7e2421ebae6..08b833beb7ad2e29a1e22775e46bc36a3ad24267 100644 (file)
@@ -172,9 +172,8 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
     // Pre-compute a few values for efficiency.
     bool isCurrency = utils::unitIsCurrency(macros.unit);
     bool isNoUnit = utils::unitIsNoUnit(macros.unit);
-    bool isPercent = isNoUnit && utils::unitIsPercent(macros.unit);
-    bool isPermille = isNoUnit && utils::unitIsPermille(macros.unit);
-    bool isCldrUnit = !isCurrency && !isNoUnit;
+    bool isPercent = utils::unitIsPercent(macros.unit);
+    bool isPermille = utils::unitIsPermille(macros.unit);
     bool isAccounting =
             macros.sign == UNUM_SIGN_ACCOUNTING || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS ||
             macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
@@ -194,6 +193,8 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
     if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) {
         unitWidth = macros.unitWidth;
     }
+    bool isCldrUnit = !isCurrency && !isNoUnit &&
+        (unitWidth == UNUM_UNIT_WIDTH_FULL_NAME || !(isPercent || isPermille));
 
     // Select the numbering system.
     LocalPointer<const NumberingSystem> nsLocal;
@@ -243,7 +244,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
     }
     if (pattern == nullptr) {
         CldrPatternStyle patternStyle;
-        if (isPercent || isPermille) {
+        if (isCldrUnit) {
+            patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
+        } else if (isPercent || isPermille) {
             patternStyle = CLDR_PATTERN_STYLE_PERCENT;
         } else if (!isCurrency || unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
             patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
index 35463612e0c1ed1819c15650dc753f8874d300b7..c07fe9e37ecf31ec6dde2b8e224e413fc55b2f8e 100644 (file)
@@ -56,6 +56,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition {
     void unitCompoundMeasure();
     void unitCurrency();
     void unitPercent();
+    void percentParity();
     void roundingFraction();
     void roundingFigures();
     void roundingFractionFigures();
index 4e6f7f5d741907cce77794527c4234f3197b31d2..2d925eee5be742cf9bb51e111fa0e245776596e9 100644 (file)
@@ -70,6 +70,10 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
         TESTCASE_AUTO(unitCompoundMeasure);
         TESTCASE_AUTO(unitCurrency);
         TESTCASE_AUTO(unitPercent);
+        if (!quick) {
+            // Slow test: run in exhaustive mode only
+            TESTCASE_AUTO(percentParity);
+        }
         TESTCASE_AUTO(roundingFraction);
         TESTCASE_AUTO(roundingFigures);
         TESTCASE_AUTO(roundingFractionFigures);
@@ -89,7 +93,11 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
         TESTCASE_AUTO(fieldPositionCoverage);
         TESTCASE_AUTO(toFormat);
         TESTCASE_AUTO(errors);
-        TESTCASE_AUTO(validRanges);
+        if (!quick) {
+            // Slow test: run in exhaustive mode only
+            // (somewhat slow to check all permutations of settings)
+            TESTCASE_AUTO(validRanges);
+        }
         TESTCASE_AUTO(copyMove);
         TESTCASE_AUTO(localPointerCAPI);
         TESTCASE_AUTO(toObject);
@@ -830,6 +838,33 @@ void NumberFormatterApiTest::unitPercent() {
             u"-98.765432%");
 }
 
+void NumberFormatterApiTest::percentParity() {
+    IcuTestErrorCode status(*this, "percentParity");
+    UnlocalizedNumberFormatter uNoUnitPercent = NumberFormatter::with().unit(NoUnit::percent());
+    UnlocalizedNumberFormatter uNoUnitPermille = NumberFormatter::with().unit(NoUnit::permille());
+    UnlocalizedNumberFormatter uMeasurePercent = NumberFormatter::with().unit(MeasureUnit::getPercent());
+    UnlocalizedNumberFormatter uMeasurePermille = NumberFormatter::with().unit(MeasureUnit::getPermille());
+
+    int32_t localeCount;
+    auto locales = Locale::getAvailableLocales(localeCount);
+    for (int32_t i=0; i<localeCount; i++) {
+        auto& locale = locales[i];
+        UnicodeString sNoUnitPercent = uNoUnitPercent.locale(locale)
+            .formatDouble(50, status).toString(status);
+        UnicodeString sNoUnitPermille = uNoUnitPermille.locale(locale)
+            .formatDouble(50, status).toString(status);
+        UnicodeString sMeasurePercent = uMeasurePercent.locale(locale)
+            .formatDouble(50, status).toString(status);
+        UnicodeString sMeasurePermille = uMeasurePermille.locale(locale)
+            .formatDouble(50, status).toString(status);
+
+        assertEquals(u"Percent, locale " + UnicodeString(locale.getName()),
+            sNoUnitPercent, sMeasurePercent);
+        assertEquals(u"Permille, locale " + UnicodeString(locale.getName()),
+            sNoUnitPermille, sMeasurePermille);
+    }
+}
+
 void NumberFormatterApiTest::roundingFraction() {
     assertFormatDescending(
             u"Integer",
@@ -2639,11 +2674,6 @@ void NumberFormatterApiTest::errors() {
 }
 
 void NumberFormatterApiTest::validRanges() {
-    if (quick) {
-        // Do not run this test except in exhaustive mode.
-        // (somewhat slow to check all permutations of settings)
-        return;
-    }
 
 #define EXPECTED_MAX_INT_FRAC_SIG 999
 
index 090398e8ef33a19a51f9fe094b1879e340f9a846..9e9b49be9a4bb83d76e19852f4e0ffbf49e2696c 100644 (file)
@@ -21,7 +21,10 @@ void DecimalQuantityTest::runIndexedTest(int32_t index, UBool exec, const char *
         TESTCASE_AUTO(testSwitchStorage);;
         TESTCASE_AUTO(testCopyMove);
         TESTCASE_AUTO(testAppend);
-        TESTCASE_AUTO(testConvertToAccurateDouble);
+        if (!quick) {
+            // Slow test: run in exhaustive mode only
+            TESTCASE_AUTO(testConvertToAccurateDouble);
+        }
         TESTCASE_AUTO(testUseApproximateDoubleWhenAble);
         TESTCASE_AUTO(testHardDoubleConversion);
         TESTCASE_AUTO(testToDouble);
index b6b74f8e3ed6f57e99e8e425b889c729b043e0ef..4adf9589d2355c047b7b00809c26439a9e7780eb 100644 (file)
@@ -185,9 +185,8 @@ class NumberFormatterImpl {
         // Pre-compute a few values for efficiency.
         boolean isCurrency = unitIsCurrency(macros.unit);
         boolean isNoUnit = unitIsNoUnit(macros.unit);
-        boolean isPercent = isNoUnit && unitIsPercent(macros.unit);
-        boolean isPermille = isNoUnit && unitIsPermille(macros.unit);
-        boolean isCldrUnit = !isCurrency && !isNoUnit;
+        boolean isPercent = unitIsPercent(macros.unit);
+        boolean isPermille = unitIsPermille(macros.unit);
         boolean isAccounting = macros.sign == SignDisplay.ACCOUNTING
                 || macros.sign == SignDisplay.ACCOUNTING_ALWAYS
                 || macros.sign == SignDisplay.ACCOUNTING_EXCEPT_ZERO;
@@ -196,6 +195,8 @@ class NumberFormatterImpl {
         if (macros.unitWidth != null) {
             unitWidth = macros.unitWidth;
         }
+        boolean isCldrUnit = !isCurrency && !isNoUnit &&
+            (unitWidth == UnitWidth.FULL_NAME || !(isPercent || isPermille));
         PluralRules rules = macros.rules;
 
         // Select the numbering system.
@@ -231,7 +232,9 @@ class NumberFormatterImpl {
         }
         if (pattern == null) {
             int patternStyle;
-            if (isPercent || isPermille) {
+            if (isCldrUnit) {
+                patternStyle = NumberFormat.NUMBERSTYLE;
+            } else if (isPercent || isPermille) {
                 patternStyle = NumberFormat.PERCENTSTYLE;
             } else if (!isCurrency || unitWidth == UnitWidth.FULL_NAME) {
                 patternStyle = NumberFormat.NUMBERSTYLE;
index 450f08ce725cc398cfff58610c8a2f7bfd803e12..6a679eff2b33be1831d12d1f8ed62201961b1f8c 100644 (file)
@@ -15,9 +15,12 @@ import com.ibm.icu.impl.StaticUnicodeSets.Key;
 import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
 import com.ibm.icu.lang.UCharacter;
 import com.ibm.icu.number.NumberFormatter;
+import com.ibm.icu.number.UnlocalizedNumberFormatter;
 import com.ibm.icu.number.Precision;
 import com.ibm.icu.text.DecimalFormatSymbols;
 import com.ibm.icu.text.UnicodeSet;
+import com.ibm.icu.util.MeasureUnit;
+import com.ibm.icu.util.NoUnit;
 import com.ibm.icu.util.ULocale;
 
 /**
@@ -87,6 +90,24 @@ public class ExhaustiveNumberTest extends TestFmwk {
                 set.contains(cp));
     }
 
+    @Test
+    public void test20417_PercentParity() {
+        UnlocalizedNumberFormatter uNoUnitPercent = NumberFormatter.with().unit(NoUnit.PERCENT);
+        UnlocalizedNumberFormatter uNoUnitPermille = NumberFormatter.with().unit(NoUnit.PERMILLE);
+        UnlocalizedNumberFormatter uMeasurePercent = NumberFormatter.with().unit(MeasureUnit.PERCENT);
+        UnlocalizedNumberFormatter uMeasurePermille = NumberFormatter.with().unit(MeasureUnit.PERMILLE);
+
+        for (ULocale locale : ULocale.getAvailableLocales()) {
+            String sNoUnitPercent = uNoUnitPercent.locale(locale).format(50).toString();
+            String sNoUnitPermille = uNoUnitPermille.locale(locale).format(50).toString();
+            String sMeasurePercent = uMeasurePercent.locale(locale).format(50).toString();
+            String sMeasurePermille = uMeasurePermille.locale(locale).format(50).toString();
+
+            assertEquals("Percent, locale " + locale, sNoUnitPercent, sMeasurePercent);
+            assertEquals("Permille, locale " + locale, sNoUnitPermille, sMeasurePermille);
+        }
+    }
+
     @Test
     public void unlimitedRoundingBigDecimal() {
         BigDecimal ten10000 = BigDecimal.valueOf(10).pow(10000);