ICU-20923 Fix compact notation with percent.

This commit is contained in:
Shane F. Carr 2020-08-14 01:44:02 -05:00
parent 2f39d33498
commit 196d5e1182
7 changed files with 227 additions and 83 deletions

View File

@ -133,6 +133,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
bool isBaseUnit = utils::unitIsBaseUnit(macros.unit);
bool isPercent = utils::unitIsPercent(macros.unit);
bool isPermille = utils::unitIsPermille(macros.unit);
bool isCompactNotation = macros.notation.fType == Notation::NTN_COMPACT;
bool isAccounting =
macros.sign == UNUM_SIGN_ACCOUNTING || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS ||
macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
@ -144,8 +145,18 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) {
unitWidth = macros.unitWidth;
}
bool isCldrUnit = !isCurrency && !isBaseUnit &&
(unitWidth == UNUM_UNIT_WIDTH_FULL_NAME || !(isPercent || isPermille));
// Use CLDR unit data for all MeasureUnits (not currency and not
// no-unit), except use the dedicated percent pattern for percent and
// permille. However, use the CLDR unit data for percent/permille if a
// long name was requested OR if compact notation is being used, since
// compact notation overrides the middle modifier (micros.modMiddle)
// normally used for the percent pattern.
bool isCldrUnit = !isCurrency
&& !isBaseUnit
&& (unitWidth == UNUM_UNIT_WIDTH_FULL_NAME
|| !(isPercent || isPermille)
|| isCompactNotation
);
// Select the numbering system.
LocalPointer<const NumberingSystem> nsLocal;
@ -232,7 +243,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
Precision precision;
if (!macros.precision.isBogus()) {
precision = macros.precision;
} else if (macros.notation.fType == Notation::NTN_COMPACT) {
} else if (isCompactNotation) {
precision = Precision::integer().withMinDigits(2);
} else if (isCurrency) {
precision = Precision::currency(UCURR_USAGE_STANDARD);
@ -254,7 +265,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
// Grouping strategy
if (!macros.grouper.isBogus()) {
fMicros.grouping = macros.grouper;
} else if (macros.notation.fType == Notation::NTN_COMPACT) {
} else if (isCompactNotation) {
// Compact notation uses minGrouping by default since ICU 59
fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_MIN2);
} else {
@ -366,7 +377,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
}
// Compact notation
if (macros.notation.fType == Notation::NTN_COMPACT) {
if (isCompactNotation) {
CompactType compactType = (isCurrency && unitWidth != UNUM_UNIT_WIDTH_FULL_NAME)
? CompactType::TYPE_CURRENCY : CompactType::TYPE_DECIMAL;
auto newCompactHandler = new CompactHandler(

View File

@ -1014,6 +1014,65 @@ void NumberFormatterApiTest::unitPercent() {
-98.7654321,
u"-98.765432%");
// ICU-20923
assertFormatDescendingBig(
u"Compact Percent",
u"compact-short percent",
u"K %",
NumberFormatter::with()
.notation(Notation::compactShort())
.unit(NoUnit::percent()),
Locale::getEnglish(),
u"88M%",
u"8.8M%",
u"876K%",
u"88K%",
u"8.8K%",
u"876%",
u"88%",
u"8.8%",
u"0%");
// ICU-20923
assertFormatDescendingBig(
u"Compact Percent with Scale",
u"compact-short percent scale/100",
u"K %x100",
NumberFormatter::with()
.notation(Notation::compactShort())
.unit(NoUnit::percent())
.scale(Scale::powerOfTen(2)),
Locale::getEnglish(),
u"8.8B%",
u"876M%",
u"88M%",
u"8.8M%",
u"876K%",
u"88K%",
u"8.8K%",
u"876%",
u"0%");
// ICU-20923
assertFormatDescendingBig(
u"Compact Percent Long Name",
u"compact-short percent unit-width-full-name",
u"K % unit-width-full-name",
NumberFormatter::with()
.notation(Notation::compactShort())
.unit(NoUnit::percent())
.unitWidth(UNUM_UNIT_WIDTH_FULL_NAME),
Locale::getEnglish(),
u"88M percent",
u"8.8M percent",
u"876K percent",
u"88K percent",
u"8.8K percent",
u"876 percent",
u"88 percent",
u"8.8 percent",
u"0 percent");
assertFormatSingle(
u"Per Percent",
u"measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name",

View File

@ -71,7 +71,11 @@ static const double kNumbersToTest[]{0, 91827.3645, -0.22222};
* Test permutations of 3 orthogonal skeleton parts from the list above.
* Compare the results against the golden data file:
* numberpermutationtest.txt
* To regenerate that file, run intltest with the -G option.
* To regenerate that file, run intltest with the -e and -G options.
* On Linux, from icu4c/source:
* make -j8 tests && (cd test/intltest && LD_LIBRARY_PATH=../../lib:../../tools/ctestfw ./intltest -e -G format/NumberTest/NumberPermutationTest)
* After re-generating the file, copy it into icu4j:
* cp test/testdata/numberpermutationtest.txt ../../icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
*/
void NumberPermutationTest::testPermutations() {
IcuTestErrorCode status(*this, "testPermutations");

View File

@ -4,15 +4,15 @@
compact-short percent unit-width-narrow
es-MX
0 %
92 k
92 k %
-0.22 %
zh-TW
0%
9.2萬
9.2萬%
-0.22%
bn-BD
%
৯২ হা
৯২ হা%
-.২২%
compact-short percent unit-width-full-name
@ -172,57 +172,57 @@ scientific/+ee/sign-always measure-unit/length-furlong unit-width-full-name
compact-short percent precision-integer
es-MX
0 %
92 k
92 k %
-0 %
zh-TW
0%
9萬
9萬%
-0%
bn-BD
%
৯২ হা
৯২ হা%
-%
compact-short percent .000
es-MX
0.000 %
91.827 k
91.827 k %
-0.222 %
zh-TW
0.000%
9.183萬
9.183萬%
-0.222%
bn-BD
.%
৯১.৮২৭ হা
৯১.৮২৭ হা%
-.২২২%
compact-short percent .##/@@@+
es-MX
0 %
91.83 k
91.83 k %
-0.222 %
zh-TW
0%
9.18萬
9.18萬%
-0.222%
bn-BD
%
৯১.৮৩ হা
৯১.৮৩ হা%
-.২২২%
compact-short percent @@
es-MX
0.0 %
92 k
92 k %
-0.22 %
zh-TW
0.0%
9.2萬
9.2萬%
-0.22%
bn-BD
.%
৯২ হা
৯২ হা%
-.২২%
compact-short currency/EUR precision-integer
@ -508,15 +508,15 @@ scientific/+ee/sign-always measure-unit/length-furlong @@
compact-short percent rounding-mode-floor
es-MX
0 %
91 k
91 k %
-0.23 %
zh-TW
0%
9.1萬
9.1萬%
-0.23%
bn-BD
%
৯১ হা
৯১ হা%
-.২৩%
compact-short currency/EUR rounding-mode-floor
@ -592,15 +592,15 @@ scientific/+ee/sign-always measure-unit/length-furlong rounding-mode-floor
compact-short percent integer-width/##00
es-MX
00 %
92 k
92 k %
-00.22 %
zh-TW
00%
09.2萬
09.2萬%
-00.22%
bn-BD
%
৯২ হা
৯২ হা%
-.২২%
compact-short currency/EUR integer-width/##00
@ -676,15 +676,15 @@ scientific/+ee/sign-always measure-unit/length-furlong integer-width/##00
compact-short percent scale/0.5
es-MX
0 %
46 k
46 k %
-0.11 %
zh-TW
0%
4.6萬
4.6萬%
-0.11%
bn-BD
%
৪৬ হা
৪৬ হা%
-.১১%
compact-short currency/EUR scale/0.5
@ -760,15 +760,15 @@ scientific/+ee/sign-always measure-unit/length-furlong scale/0.5
compact-short percent group-on-aligned
es-MX
0 %
92 k
92 k %
-0.22 %
zh-TW
0%
9.2萬
9.2萬%
-0.22%
bn-BD
%
৯২ হা
৯২ হা%
-.২২%
compact-short currency/EUR group-on-aligned
@ -844,15 +844,15 @@ scientific/+ee/sign-always measure-unit/length-furlong group-on-aligned
compact-short percent latin
es-MX
0 %
92 k
92 k %
-0.22 %
zh-TW
0%
9.2萬
9.2萬%
-0.22%
bn-BD
0%
92 হা
92 হা%
-0.22%
compact-short currency/EUR latin
@ -928,15 +928,15 @@ scientific/+ee/sign-always measure-unit/length-furlong latin
compact-short percent sign-accounting-except-zero
es-MX
0 %
+92 k
+92 k %
-0.22 %
zh-TW
0%
+9.2萬
+9.2萬%
-0.22%
bn-BD
%
+৯২ হা
+৯২ হা%
-.২২%
compact-short currency/EUR sign-accounting-except-zero
@ -1012,15 +1012,15 @@ scientific/+ee/sign-always measure-unit/length-furlong sign-accounting-except-ze
compact-short percent decimal-always
es-MX
0. %
92. k
92. k %
-0.22 %
zh-TW
0.%
9.2萬
9.2萬%
-0.22%
bn-BD
.%
৯২. হা
৯২. হা%
-.২২%
compact-short currency/EUR decimal-always

View File

@ -182,6 +182,7 @@ class NumberFormatterImpl {
boolean isBaseUnit = unitIsBaseUnit(macros.unit);
boolean isPercent = unitIsPercent(macros.unit);
boolean isPermille = unitIsPermille(macros.unit);
boolean isCompactNotation = (macros.notation instanceof CompactNotation);
boolean isAccounting = macros.sign == SignDisplay.ACCOUNTING
|| macros.sign == SignDisplay.ACCOUNTING_ALWAYS
|| macros.sign == SignDisplay.ACCOUNTING_EXCEPT_ZERO;
@ -190,8 +191,18 @@ class NumberFormatterImpl {
if (macros.unitWidth != null) {
unitWidth = macros.unitWidth;
}
boolean isCldrUnit = !isCurrency && !isBaseUnit &&
(unitWidth == UnitWidth.FULL_NAME || !(isPercent || isPermille));
// Use CLDR unit data for all MeasureUnits (not currency and not
// no-unit), except use the dedicated percent pattern for percent and
// permille. However, use the CLDR unit data for percent/permille if a
// long name was requested OR if compact notation is being used, since
// compact notation overrides the middle modifier (micros.modMiddle)
// normally used for the percent pattern.
boolean isCldrUnit = !isCurrency
&& !isBaseUnit
&& (unitWidth == UnitWidth.FULL_NAME
|| !(isPercent || isPermille)
|| isCompactNotation
);
PluralRules rules = macros.rules;
// Select the numbering system.
@ -252,7 +263,7 @@ class NumberFormatterImpl {
// Rounding strategy
if (macros.precision != null) {
micros.rounder = macros.precision;
} else if (macros.notation instanceof CompactNotation) {
} else if (isCompactNotation) {
micros.rounder = Precision.COMPACT_STRATEGY;
} else if (isCurrency) {
micros.rounder = Precision.MONETARY_STANDARD;
@ -270,7 +281,7 @@ class NumberFormatterImpl {
micros.grouping = (Grouper) macros.grouping;
} else if (macros.grouping instanceof GroupingStrategy) {
micros.grouping = Grouper.forStrategy((GroupingStrategy) macros.grouping);
} else if (macros.notation instanceof CompactNotation) {
} else if (isCompactNotation) {
// Compact notation uses minGrouping by default since ICU 59
micros.grouping = Grouper.forStrategy(GroupingStrategy.MIN2);
} else {
@ -356,7 +367,7 @@ class NumberFormatterImpl {
}
// Compact notation
if (macros.notation instanceof CompactNotation) {
if (isCompactNotation) {
if (rules == null) {
// Lazily create PluralRules
rules = PluralRules.forLocale(macros.loc);

View File

@ -4,15 +4,15 @@
compact-short percent unit-width-narrow
es-MX
0 %
92 k
92 k %
-0.22 %
zh-TW
0%
9.2萬
9.2萬%
-0.22%
bn-BD
%
৯২ হা
৯২ হা%
-.২২%
compact-short percent unit-width-full-name
@ -172,57 +172,57 @@ scientific/+ee/sign-always measure-unit/length-furlong unit-width-full-name
compact-short percent precision-integer
es-MX
0 %
92 k
92 k %
-0 %
zh-TW
0%
9萬
9萬%
-0%
bn-BD
%
৯২ হা
৯২ হা%
-%
compact-short percent .000
es-MX
0.000 %
91.827 k
91.827 k %
-0.222 %
zh-TW
0.000%
9.183萬
9.183萬%
-0.222%
bn-BD
.%
৯১.৮২৭ হা
৯১.৮২৭ হা%
-.২২২%
compact-short percent .##/@@@+
es-MX
0 %
91.83 k
91.83 k %
-0.222 %
zh-TW
0%
9.18萬
9.18萬%
-0.222%
bn-BD
%
৯১.৮৩ হা
৯১.৮৩ হা%
-.২২২%
compact-short percent @@
es-MX
0.0 %
92 k
92 k %
-0.22 %
zh-TW
0.0%
9.2萬
9.2萬%
-0.22%
bn-BD
.%
৯২ হা
৯২ হা%
-.২২%
compact-short currency/EUR precision-integer
@ -508,15 +508,15 @@ scientific/+ee/sign-always measure-unit/length-furlong @@
compact-short percent rounding-mode-floor
es-MX
0 %
91 k
91 k %
-0.23 %
zh-TW
0%
9.1萬
9.1萬%
-0.23%
bn-BD
%
৯১ হা
৯১ হা%
-.২৩%
compact-short currency/EUR rounding-mode-floor
@ -592,15 +592,15 @@ scientific/+ee/sign-always measure-unit/length-furlong rounding-mode-floor
compact-short percent integer-width/##00
es-MX
00 %
92 k
92 k %
-00.22 %
zh-TW
00%
09.2萬
09.2萬%
-00.22%
bn-BD
%
৯২ হা
৯২ হা%
-.২২%
compact-short currency/EUR integer-width/##00
@ -676,15 +676,15 @@ scientific/+ee/sign-always measure-unit/length-furlong integer-width/##00
compact-short percent scale/0.5
es-MX
0 %
46 k
46 k %
-0.11 %
zh-TW
0%
4.6萬
4.6萬%
-0.11%
bn-BD
%
৪৬ হা
৪৬ হা%
-.১১%
compact-short currency/EUR scale/0.5
@ -760,15 +760,15 @@ scientific/+ee/sign-always measure-unit/length-furlong scale/0.5
compact-short percent group-on-aligned
es-MX
0 %
92 k
92 k %
-0.22 %
zh-TW
0%
9.2萬
9.2萬%
-0.22%
bn-BD
%
৯২ হা
৯২ হা%
-.২২%
compact-short currency/EUR group-on-aligned
@ -844,15 +844,15 @@ scientific/+ee/sign-always measure-unit/length-furlong group-on-aligned
compact-short percent latin
es-MX
0 %
92 k
92 k %
-0.22 %
zh-TW
0%
9.2萬
9.2萬%
-0.22%
bn-BD
0%
92 হা
92 হা%
-0.22%
compact-short currency/EUR latin
@ -928,15 +928,15 @@ scientific/+ee/sign-always measure-unit/length-furlong latin
compact-short percent sign-accounting-except-zero
es-MX
0 %
+92 k
+92 k %
-0.22 %
zh-TW
0%
+9.2萬
+9.2萬%
-0.22%
bn-BD
%
+৯২ হা
+৯২ হা%
-.২২%
compact-short currency/EUR sign-accounting-except-zero
@ -1012,15 +1012,15 @@ scientific/+ee/sign-always measure-unit/length-furlong sign-accounting-except-ze
compact-short percent decimal-always
es-MX
0. %
92. k
92. k %
-0.22 %
zh-TW
0.%
9.2萬
9.2萬%
-0.22%
bn-BD
.%
৯২. হা
৯২. হা%
-.২২%
compact-short currency/EUR decimal-always

View File

@ -967,6 +967,65 @@ public class NumberFormatterApiTest {
-98.7654321,
"-98.765432%");
// ICU-20923
assertFormatDescendingBig(
"Compact Percent",
"compact-short percent",
"K %",
NumberFormatter.with()
.notation(Notation.compactShort())
.unit(NoUnit.PERCENT),
ULocale.ENGLISH,
"88M%",
"8.8M%",
"876K%",
"88K%",
"8.8K%",
"876%",
"88%",
"8.8%",
"0%");
// ICU-20923
assertFormatDescendingBig(
"Compact Percent with Scale",
"compact-short percent scale/100",
"K %x100",
NumberFormatter.with()
.notation(Notation.compactShort())
.unit(NoUnit.PERCENT)
.scale(Scale.powerOfTen(2)),
ULocale.ENGLISH,
"8.8B%",
"876M%",
"88M%",
"8.8M%",
"876K%",
"88K%",
"8.8K%",
"876%",
"0%");
// ICU-20923
assertFormatDescendingBig(
"Compact Percent Long Name",
"compact-short percent unit-width-full-name",
"K % unit-width-full-name",
NumberFormatter.with()
.notation(Notation.compactShort())
.unit(NoUnit.PERCENT)
.unitWidth(UnitWidth.FULL_NAME),
ULocale.ENGLISH,
"88M percent",
"8.8M percent",
"876K percent",
"88K percent",
"8.8K percent",
"876 percent",
"88 percent",
"8.8 percent",
"0 percent");
assertFormatSingle(
"Per Percent",
"measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name",