ICU-20417 Adding parity between NoUnit and MeasureUnit Percent for short forms.
- Use Percent pattern for MeasureUnit Percent instead of the short or narrow form pattern from CLDR.
diff --git a/icu4c/source/i18n/number_formatimpl.cpp b/icu4c/source/i18n/number_formatimpl.cpp
index a7f162e..08b833b 100644
--- a/icu4c/source/i18n/number_formatimpl.cpp
+++ b/icu4c/source/i18n/number_formatimpl.cpp
@@ -172,9 +172,8 @@
// 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 @@
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 @@
}
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;
diff --git a/icu4c/source/test/intltest/numbertest.h b/icu4c/source/test/intltest/numbertest.h
index 3546361..c07fe9e 100644
--- a/icu4c/source/test/intltest/numbertest.h
+++ b/icu4c/source/test/intltest/numbertest.h
@@ -56,6 +56,7 @@
void unitCompoundMeasure();
void unitCurrency();
void unitPercent();
+ void percentParity();
void roundingFraction();
void roundingFigures();
void roundingFractionFigures();
diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp
index 4e6f7f5..2d925ee 100644
--- a/icu4c/source/test/intltest/numbertest_api.cpp
+++ b/icu4c/source/test/intltest/numbertest_api.cpp
@@ -70,6 +70,10 @@
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 @@
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 @@
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::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
diff --git a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
index 090398e..9e9b49b 100644
--- a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
+++ b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
@@ -21,7 +21,10 @@
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);
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
index b6b74f8..4adf958 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
@@ -185,9 +185,8 @@
// 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 @@
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 @@
}
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;
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/ExhaustiveNumberTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/ExhaustiveNumberTest.java
index 450f08c..6a679ef 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/ExhaustiveNumberTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/ExhaustiveNumberTest.java
@@ -15,9 +15,12 @@
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;
/**
@@ -88,6 +91,24 @@
}
@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);
BigDecimal longFraction = ten10000.subtract(BigDecimal.ONE).divide(ten10000);