From: Shane F. Carr Date: Wed, 10 Mar 2021 02:29:59 +0000 (+0000) Subject: ICU-21330 Use =0 and =1 plural forms in compact notation X-Git-Tag: release-69-rc~16 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c26d99b3a6bf2df80c172428a0dd85ac4e13441d;p=icu ICU-21330 Use =0 and =1 plural forms in compact notation See #1632 --- diff --git a/icu4c/source/i18n/number_compact.cpp b/icu4c/source/i18n/number_compact.cpp index d781b6fada2..8f898e70470 100644 --- a/icu4c/source/i18n/number_compact.cpp +++ b/icu4c/source/i18n/number_compact.cpp @@ -55,7 +55,7 @@ int32_t countZeros(const UChar *patternString, int32_t patternLength) { } // namespace // NOTE: patterns and multipliers both get zero-initialized. -CompactData::CompactData() : patterns(), multipliers(), largestMagnitude(0), isEmpty(TRUE) { +CompactData::CompactData() : patterns(), multipliers(), largestMagnitude(0), isEmpty(true) { } void CompactData::populate(const Locale &locale, const char *nsName, CompactStyle compactStyle, @@ -104,14 +104,30 @@ int32_t CompactData::getMultiplier(int32_t magnitude) const { return multipliers[magnitude]; } -const UChar *CompactData::getPattern(int32_t magnitude, StandardPlural::Form plural) const { +const UChar *CompactData::getPattern( + int32_t magnitude, + const PluralRules *rules, + const DecimalQuantity &dq) const { if (magnitude < 0) { return nullptr; } if (magnitude > largestMagnitude) { magnitude = largestMagnitude; } - const UChar *patternString = patterns[getIndex(magnitude, plural)]; + const UChar *patternString = nullptr; + if (dq.hasIntegerValue()) { + int64_t i = dq.toLong(true); + if (i == 0) { + patternString = patterns[getIndex(magnitude, StandardPlural::Form::EQ_0)]; + } else if (i == 1) { + patternString = patterns[getIndex(magnitude, StandardPlural::Form::EQ_1)]; + } + if (patternString != nullptr) { + return patternString; + } + } + StandardPlural::Form plural = utils::getStandardPlural(rules, dq); + patternString = patterns[getIndex(magnitude, plural)]; if (patternString == nullptr && plural != StandardPlural::OTHER) { // Fall back to "other" plural variant patternString = patterns[getIndex(magnitude, StandardPlural::OTHER)]; @@ -166,12 +182,6 @@ void CompactData::CompactDataSink::put(const char *key, ResourceValue &value, UB ResourceTable pluralVariantsTable = value.getTable(status); if (U_FAILURE(status)) { return; } for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) { - - if (uprv_strcmp(key, "0") == 0 || uprv_strcmp(key, "1") == 0) { - // TODO(ICU-21258): Handle this case. For now, skip. - continue; - } - // Skip this magnitude/plural if we already have it from a child locale. // Note: This also skips USE_FALLBACK entries. StandardPlural::Form plural = StandardPlural::fromString(key, status); @@ -296,8 +306,7 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr magnitude -= multiplier; } - StandardPlural::Form plural = utils::getStandardPlural(rules, quantity); - const UChar *patternString = data.getPattern(magnitude, plural); + const UChar *patternString = data.getPattern(magnitude, rules, quantity); if (patternString == nullptr) { // Use the default (non-compact) modifier. // No need to take any action. diff --git a/icu4c/source/i18n/number_compact.h b/icu4c/source/i18n/number_compact.h index 199d39f6591..9802b9fb10e 100644 --- a/icu4c/source/i18n/number_compact.h +++ b/icu4c/source/i18n/number_compact.h @@ -28,7 +28,10 @@ class CompactData : public MultiplierProducer { int32_t getMultiplier(int32_t magnitude) const U_OVERRIDE; - const UChar *getPattern(int32_t magnitude, StandardPlural::Form plural) const; + const UChar *getPattern( + int32_t magnitude, + const PluralRules *rules, + const DecimalQuantity &dq) const; void getUniquePatterns(UVector &output, UErrorCode &status) const; diff --git a/icu4c/source/i18n/standardplural.cpp b/icu4c/source/i18n/standardplural.cpp index 0391034b3e4..5a6069bf7dd 100644 --- a/icu4c/source/i18n/standardplural.cpp +++ b/icu4c/source/i18n/standardplural.cpp @@ -23,7 +23,7 @@ U_NAMESPACE_BEGIN static const char *gKeywords[StandardPlural::COUNT] = { - "zero", "one", "two", "few", "many", "other" + "zero", "one", "two", "few", "many", "other", "=0", "=1" }; const char *StandardPlural::getKeyword(Form p) { @@ -60,21 +60,55 @@ int32_t StandardPlural::indexOrNegativeFromString(const char *keyword) { return ZERO; } break; + case '=': + if (uprv_strcmp(keyword, "0") == 0) { + return EQ_0; + } else if (uprv_strcmp(keyword, "1") == 0) { + return EQ_1; + } + break; + // Also allow "0" and "1" + case '0': + if (*keyword == 0) { + return EQ_0; + } + break; + case '1': + if (*keyword == 0) { + return EQ_1; + } + break; default: break; } return -1; } -static const UChar gZero[] = { 0x7A, 0x65, 0x72, 0x6F }; -static const UChar gOne[] = { 0x6F, 0x6E, 0x65 }; -static const UChar gTwo[] = { 0x74, 0x77, 0x6F }; -static const UChar gFew[] = { 0x66, 0x65, 0x77 }; -static const UChar gMany[] = { 0x6D, 0x61, 0x6E, 0x79 }; -static const UChar gOther[] = { 0x6F, 0x74, 0x68, 0x65, 0x72 }; +static const UChar gZero[] = u"zero"; +static const UChar gOne[] = u"one"; +static const UChar gTwo[] = u"two"; +static const UChar gFew[] = u"few"; +static const UChar gMany[] = u"many"; +static const UChar gOther[] = u"other"; +static const UChar gEq0[] = u"=0"; +static const UChar gEq1[] = u"=1"; int32_t StandardPlural::indexOrNegativeFromString(const UnicodeString &keyword) { switch (keyword.length()) { + case 1: + if (keyword.charAt(0) == '0') { + return EQ_0; + } else if (keyword.charAt(0) == '1') { + return EQ_1; + } + break; + case 2: + if (keyword.compare(gEq0, 2) == 0) { + return EQ_0; + } else if (keyword.compare(gEq1, 2) == 0) { + return EQ_1; + } + break; case 3: if (keyword.compare(gOne, 3) == 0) { return ONE; diff --git a/icu4c/source/i18n/standardplural.h b/icu4c/source/i18n/standardplural.h index 33e1d605f68..16593065c8a 100644 --- a/icu4c/source/i18n/standardplural.h +++ b/icu4c/source/i18n/standardplural.h @@ -35,6 +35,8 @@ public: FEW, MANY, OTHER, + EQ_0, + EQ_1, COUNT }; diff --git a/icu4c/source/test/intltest/numbertest.h b/icu4c/source/test/intltest/numbertest.h index 39e888582f7..49f9b12ab69 100644 --- a/icu4c/source/test/intltest/numbertest.h +++ b/icu4c/source/test/intltest/numbertest.h @@ -198,6 +198,7 @@ class DecimalQuantityTest : public IntlTest { void testConvertToAccurateDouble(); void testUseApproximateDoubleWhenAble(); void testHardDoubleConversion(); + void testFitsInLong(); void testToDouble(); void testMaxDigits(); void testNickelRounding(); diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp index 4d74a55842b..689af5c4885 100644 --- a/icu4c/source/test/intltest/numbertest_api.cpp +++ b/icu4c/source/test/intltest/numbertest_api.cpp @@ -498,16 +498,14 @@ void NumberFormatterApiTest::notationCompact() { 1e7, u"1000\u842C"); - if (!logKnownIssue("21258", "StandardPlural cannot handle keywords 1, 0")) { - assertFormatSingle( - u"Compact with plural form =1 (ICU-21258)", - u"compact-long", - u"K", - NumberFormatter::with().notation(Notation::compactLong()), - Locale("fr-FR"), - 1e3, - u"mille"); - } + assertFormatSingle( + u"Compact with plural form =1 (ICU-21258)", + u"compact-long", + u"KK", + NumberFormatter::with().notation(Notation::compactLong()), + Locale("fr-FR"), + 1e3, + u"mille"); assertFormatSingle( u"Compact Infinity", diff --git a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp index 610df9658c8..7403dda7e75 100644 --- a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp +++ b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp @@ -27,6 +27,7 @@ void DecimalQuantityTest::runIndexedTest(int32_t index, UBool exec, const char * } TESTCASE_AUTO(testUseApproximateDoubleWhenAble); TESTCASE_AUTO(testHardDoubleConversion); + TESTCASE_AUTO(testFitsInLong); TESTCASE_AUTO(testToDouble); TESTCASE_AUTO(testMaxDigits); TESTCASE_AUTO(testNickelRounding); @@ -357,6 +358,44 @@ void DecimalQuantityTest::testHardDoubleConversion() { } } +void DecimalQuantityTest::testFitsInLong() { + IcuTestErrorCode status(*this, "testFitsInLong"); + DecimalQuantity quantity; + quantity.setToInt(0); + assertTrue("Zero should fit", quantity.fitsInLong()); + quantity.setToInt(42); + assertTrue("Small int should fit", quantity.fitsInLong()); + quantity.setToDouble(0.1); + assertFalse("Fraction should not fit", quantity.fitsInLong()); + quantity.setToDouble(42.1); + assertFalse("Fraction should not fit", quantity.fitsInLong()); + quantity.setToLong(1000000); + assertTrue("Large low-precision int should fit", quantity.fitsInLong()); + quantity.setToLong(1000000000000000000L); + assertTrue("10^19 should fit", quantity.fitsInLong()); + quantity.setToLong(1234567890123456789L); + assertTrue("A number between 10^19 and max long should fit", quantity.fitsInLong()); + quantity.setToLong(1234567890000000000L); + assertTrue("A number with trailing zeros less than max long should fit", quantity.fitsInLong()); + quantity.setToLong(9223372026854775808L); + assertTrue("A number less than max long but with similar digits should fit", + quantity.fitsInLong()); + quantity.setToLong(9223372036854775806L); + assertTrue("One less than max long should fit", quantity.fitsInLong()); + quantity.setToLong(9223372036854775807L); + assertTrue("Max long should fit", quantity.fitsInLong()); + assertEquals("Max long should equal toLong", 9223372036854775807L, quantity.toLong(false)); + quantity.setToDecNumber("9223372036854775808", status); + assertFalse("One greater than max long should not fit", quantity.fitsInLong()); + assertEquals("toLong(true) should truncate", 223372036854775808L, quantity.toLong(true)); + quantity.setToDecNumber("9223372046854775806", status); + assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong()); + quantity.setToDecNumber("9223372046800000000", status); + assertFalse("A large 10^19 number with trailing zeros should not fit", quantity.fitsInLong()); + quantity.setToDecNumber("10000000000000000000", status); + assertFalse("10^20 should not fit", quantity.fitsInLong()); +} + void DecimalQuantityTest::testToDouble() { IcuTestErrorCode status(*this, "testToDouble"); static const struct TestCase { @@ -531,12 +570,12 @@ void DecimalQuantityTest::testScientificAndCompactSuppressedExponent() { {u"scientific", 0.012, u"1,2E-2", 0L, 0.012, u"0.012", -2, -2}, {u"", 999.9, u"999,9", 999L, 999.9, u"999.9", 0, 0}, - {u"compact-long", 999.9, u"1 millier", 1000L, 1000.0, u"1000", 3, 3}, + {u"compact-long", 999.9, u"mille", 1000L, 1000.0, u"1000", 3, 3}, {u"compact-short", 999.9, u"1 k", 1000L, 1000.0, u"1000", 3, 3}, {u"scientific", 999.9, u"9,999E2", 999L, 999.9, u"999.9", 2, 2}, {u"", 1000.0, u"1 000", 1000L, 1000.0, u"1000", 0, 0}, - {u"compact-long", 1000.0, u"1 millier", 1000L, 1000.0, u"1000", 3, 3}, + {u"compact-long", 1000.0, u"mille", 1000L, 1000.0, u"1000", 3, 3}, {u"compact-short", 1000.0, u"1 k", 1000L, 1000.0, u"1000", 3, 3}, {u"scientific", 1000.0, u"1E3", 1000L, 1000.0, u"1000", 3, 3}, }; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java index d77a7ff6e04..ff9fc7ddbae 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/StandardPlural.java @@ -22,7 +22,9 @@ public enum StandardPlural { TWO("two"), FEW("few"), MANY("many"), - OTHER("other"); + OTHER("other"), + EQ_0("=0"), + EQ_1("=1"); /** * Numeric index of OTHER, same as OTHER.ordinal(). @@ -60,6 +62,20 @@ public enum StandardPlural { */ public static final StandardPlural orNullFromString(CharSequence keyword) { switch (keyword.length()) { + case 1: + if (keyword.charAt(0) == '0') { + return EQ_0; + } else if (keyword.charAt(0) == '1') { + return EQ_1; + } + break; + case 2: + if ("=0".contentEquals(keyword)) { + return EQ_0; + } else if ("=1".contentEquals(keyword)) { + return EQ_1; + } + break; case 3: if ("one".contentEquals(keyword)) { return ONE; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java index b3e536afde3..1cc28992cff 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/CompactData.java @@ -10,6 +10,7 @@ import com.ibm.icu.impl.ICUData; import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.impl.StandardPlural; import com.ibm.icu.impl.UResource; +import com.ibm.icu.text.PluralRules; import com.ibm.icu.text.CompactDecimalFormat.CompactStyle; import com.ibm.icu.util.ICUException; import com.ibm.icu.util.ULocale; @@ -99,10 +100,6 @@ public class CompactData implements MultiplierProducer { byte magnitude = (byte) (magnitudeEntry.getKey().length() - 1); for (Map.Entry pluralEntry : magnitudeEntry.getValue().entrySet()) { String pluralString = pluralEntry.getKey().toString(); - if ("0".equals(pluralString) || "1".equals(pluralString)) { - // TODO(ICU-21258): Handle this case. For now, skip. - continue; - } StandardPlural plural = StandardPlural.fromString(pluralString); String patternString = pluralEntry.getValue().toString(); patterns[getIndex(magnitude, plural)] = patternString; @@ -130,14 +127,27 @@ public class CompactData implements MultiplierProducer { return multipliers[magnitude]; } - public String getPattern(int magnitude, StandardPlural plural) { + public String getPattern(int magnitude, PluralRules rules, DecimalQuantity dq) { if (magnitude < 0) { return null; } if (magnitude > largestMagnitude) { magnitude = largestMagnitude; } - String patternString = patterns[getIndex(magnitude, plural)]; + String patternString = null; + if (dq.isHasIntegerValue()) { + long i = dq.toLong(true); + if (i == 0) { + patternString = patterns[getIndex(magnitude, StandardPlural.EQ_0)]; + } else if (i == 1) { + patternString = patterns[getIndex(magnitude, StandardPlural.EQ_1)]; + } + if (patternString != null) { + return patternString; + } + } + StandardPlural plural = dq.getStandardPlural(rules); + patternString = patterns[getIndex(magnitude, plural)]; if (patternString == null && plural != StandardPlural.OTHER) { // Fall back to "other" plural variant patternString = patterns[getIndex(magnitude, StandardPlural.OTHER)]; @@ -181,12 +191,6 @@ public class CompactData implements MultiplierProducer { // Iterate over the plural variants ("one", "other", etc) UResource.Table pluralVariantsTable = value.getTable(); for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) { - - if ("0".equals(key.toString()) || "1".equals(key.toString())) { - // TODO(ICU-21258): Handle this case. For now, skip. - continue; - } - // Skip this magnitude/plural if we already have it from a child locale. // Note: This also skips USE_FALLBACK entries. StandardPlural plural = StandardPlural.fromString(key.toString()); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java index d33f407c28e..a571b65c71c 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java @@ -167,6 +167,18 @@ public interface DecimalQuantity extends PluralRules.IFixedDecimal { public BigDecimal toBigDecimal(); + /** + * Returns a long approximating the decimal quantity. A long can only represent the + * integral part of the number. Note: this method incorporates the value of + * {@code getExponent} (for cases such as compact notation) to return the proper long + * value represented by the result. + * + * @param truncateIfOverflow if false and the number does NOT fit, fails with an error. + * See comment about call site guards in DecimalQuantity_AbstractBCD.java + * @return A 64-bit integer representation of the internal number. + */ + public long toLong(boolean truncateIfOverflow); + public void setToBigDecimal(BigDecimal input); public int maxRepresentableDigits(); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java index 2d98cc2e098..510177d3132 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java @@ -233,6 +233,11 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity { exponent = exponent + delta; } + @Override + public boolean isHasIntegerValue() { + return scale >= 0; + } + @Override public StandardPlural getStandardPlural(PluralRules rules) { if (rules == null) { @@ -603,15 +608,7 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity { scale -= fracLength; } - /** - * Returns a long approximating the internal BCD. A long can only represent the integral part of the - * number. Note: this method incorporates the value of {@code exponent} - * (for cases such as compact notation) to return the proper long value - * represented by the result. - * - * @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. - * @return A 64-bit integer representation of the internal BCD. - */ + @Override public long toLong(boolean truncateIfOverflow) { // NOTE: Call sites should be guarded by fitsInLong(), like this: // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java b/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java index 38011434308..0b5693788a9 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java @@ -138,8 +138,7 @@ public class CompactNotation extends Notation { magnitude -= multiplier; } - StandardPlural plural = quantity.getStandardPlural(rules); - String patternString = data.getPattern(magnitude, plural); + String patternString = data.getPattern(magnitude, rules, quantity); if (patternString == null) { // Use the default (non-compact) modifier. // No need to take any action. diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java index 870b9476b8f..8ebc31bcbf4 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/PluralRules.java @@ -550,6 +550,14 @@ public class PluralRules implements Serializable { */ @Deprecated public boolean isInfinite(); + + /** + * Whether the number has no nonzero fraction digits. + * @internal CLDR + * @deprecated This API is ICU internal only. + */ + @Deprecated + public boolean isHasIntegerValue(); } /** @@ -639,6 +647,7 @@ public class PluralRules implements Serializable { * @deprecated This API is ICU internal only. */ @Deprecated + @Override public boolean isHasIntegerValue() { return hasIntegerValue; } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java index afc73dcdd95..24aedabd1ed 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/impl/number/DecimalQuantity_SimpleStorage.java @@ -325,6 +325,16 @@ public class DecimalQuantity_SimpleStorage implements DecimalQuantity { primary = -1; } + @Override + public long toLong(boolean truncateIfOverflow) { + BigDecimal temp = toBigDecimal().setScale(0, RoundingMode.FLOOR); + if (truncateIfOverflow) { + return temp.longValue(); + } else { + return temp.longValueExact(); + } + } + @Override public void setMinInteger(int minInt) { // Graceful failures for bogus input @@ -940,4 +950,9 @@ public class DecimalQuantity_SimpleStorage implements DecimalQuantity { public void adjustExponent(int delta) { origPrimaryScale = origPrimaryScale + delta; } + + @Override + public boolean isHasIntegerValue() { + return scaleBigDecimal(toBigDecimal()) >= 0; + } } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java index ec2d5982197..f8d961d0e98 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/DecimalQuantityTest.java @@ -269,6 +269,10 @@ public class DecimalQuantityTest extends TestFmwk { q0.toBigDecimal(), q1.toBigDecimal()); + assertEquals("Different long values (" + q0 + ", " + q1 + ")", + q0.toLong(true), + q1.toLong(true)); + q0.roundToInfinity(); q1.roundToInfinity(); @@ -456,8 +460,16 @@ public class DecimalQuantityTest extends TestFmwk { assertTrue("One less than max long should fit", quantity.fitsInLong()); quantity.setToLong(9223372036854775807L); assertTrue("Max long should fit", quantity.fitsInLong()); + assertEquals("Max long should equal toLong", 9223372036854775807L, quantity.toLong(false)); quantity.setToBigInteger(new BigInteger("9223372036854775808")); - assertFalse("One greater than max long long should not fit", quantity.fitsInLong()); + assertFalse("One greater than max long should not fit", quantity.fitsInLong()); + assertEquals("toLong(true) should truncate", 223372036854775808L, quantity.toLong(true)); + try { + quantity.toLong(false); + fail("One greater than max long is not convertible to long"); + } catch (ArithmeticException | AssertionError e) { + // expected + } quantity.setToBigInteger(new BigInteger("9223372046854775806")); assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong()); quantity.setToBigInteger(new BigInteger("9223372046800000000")); @@ -652,12 +664,12 @@ public class DecimalQuantityTest extends TestFmwk { {"scientific", 0.012, "1,2E-2", 0L, 0.012, new BigDecimal("0.012"), "0.012", -2, -2}, {"", 999.9, "999,9", 999L, 999.9, new BigDecimal("999.9"), "999.9", 0, 0}, - {"compact-long", 999.9, "1 millier", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, + {"compact-long", 999.9, "mille", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, {"compact-short", 999.9, "1 k", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, {"scientific", 999.9, "9,999E2", 999L, 999.9, new BigDecimal("999.9"), "999.9", 2, 2}, {"", 1000.0, "1 000", 1000L, 1000.0, new BigDecimal("1000"), "1000", 0, 0}, - {"compact-long", 1000.0, "1 millier", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, + {"compact-long", 1000.0, "mille", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, {"compact-short", 1000.0, "1 k", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, {"scientific", 1000.0, "1E3", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3, 3}, }; diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java index 66a688039ba..cb57092d31a 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java @@ -443,16 +443,14 @@ public class NumberFormatterApiTest extends TestFmwk { 1e7, "1000\u842C"); - if (!logKnownIssue("21258", "StandardPlural cannot handle keywords 1, 0")) { - assertFormatSingle( - "Compact with plural form =1 (ICU-21258)", - "compact-long", - "K", - NumberFormatter.with().notation(Notation.compactLong()), - ULocale.FRANCE, - 1e3, - "mille"); - } + assertFormatSingle( + "Compact with plural form =1 (ICU-21258)", + "compact-long", + "KK", + NumberFormatter.with().notation(Notation.compactLong()), + ULocale.FRANCE, + 1e3, + "mille"); assertFormatSingle( "Compact Infinity",