mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 15:42:14 +00:00
ICU-21519 Add PluralOperand 'c' as alias to 'e', parse FixedDecimal strings
This commit is contained in:
parent
2f89152830
commit
c263b5b370
11 changed files with 466 additions and 145 deletions
|
@ -273,6 +273,9 @@ double DecimalQuantity::getPluralOperand(PluralOperand operand) const {
|
|||
return fractionCountWithoutTrailingZeros();
|
||||
case PLURAL_OPERAND_E:
|
||||
return static_cast<double>(getExponent());
|
||||
case PLURAL_OPERAND_C:
|
||||
// Plural operand `c` is currently an alias for `e`.
|
||||
return static_cast<double>(getExponent());
|
||||
default:
|
||||
return std::abs(toDouble());
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ static const UChar PK_VAR_I[]={LOW_I,0};
|
|||
static const UChar PK_VAR_F[]={LOW_F,0};
|
||||
static const UChar PK_VAR_T[]={LOW_T,0};
|
||||
static const UChar PK_VAR_E[]={LOW_E,0};
|
||||
static const UChar PK_VAR_C[]={LOW_C,0};
|
||||
static const UChar PK_VAR_V[]={LOW_V,0};
|
||||
static const UChar PK_WITHIN[]={LOW_W,LOW_I,LOW_T,LOW_H,LOW_I,LOW_N,0};
|
||||
static const UChar PK_DECIMAL[]={LOW_D,LOW_E,LOW_C,LOW_I,LOW_M,LOW_A,LOW_L,0};
|
||||
|
@ -421,7 +422,6 @@ getSamplesFromString(const UnicodeString &samples, double *destDbl,
|
|||
destFd[sampleCount++] = fixed;
|
||||
}
|
||||
} else {
|
||||
|
||||
FixedDecimal fixedLo(sampleRange.tempSubStringBetween(0, tildeIndex), status);
|
||||
FixedDecimal fixedHi(sampleRange.tempSubStringBetween(tildeIndex+1), status);
|
||||
double rangeLo = fixedLo.source;
|
||||
|
@ -514,6 +514,7 @@ PluralRules::getSamples(const UnicodeString &keyword, FixedDecimal *dest,
|
|||
if (rc == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t numSamples = getSamplesFromString(rc->fIntegerSamples, nullptr, dest, destCapacity, status);
|
||||
if (numSamples == 0) {
|
||||
numSamples = getSamplesFromString(rc->fDecimalSamples, nullptr, dest, destCapacity, status);
|
||||
|
@ -706,6 +707,7 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr
|
|||
case tVariableF:
|
||||
case tVariableT:
|
||||
case tVariableE:
|
||||
case tVariableC:
|
||||
case tVariableV:
|
||||
U_ASSERT(curAndConstraint != nullptr);
|
||||
curAndConstraint->digitsType = type;
|
||||
|
@ -1092,6 +1094,8 @@ static UnicodeString tokenString(tokenType tok) {
|
|||
s.append(LOW_T); break;
|
||||
case tVariableE:
|
||||
s.append(LOW_E); break;
|
||||
case tVariableC:
|
||||
s.append(LOW_C); break;
|
||||
default:
|
||||
s.append(TILDE);
|
||||
}
|
||||
|
@ -1269,6 +1273,7 @@ PluralRuleParser::checkSyntax(UErrorCode &status)
|
|||
case tVariableF:
|
||||
case tVariableT:
|
||||
case tVariableE:
|
||||
case tVariableC:
|
||||
case tVariableV:
|
||||
if (type != tIs && type != tMod && type != tIn &&
|
||||
type != tNot && type != tWithin && type != tEqual && type != tNotEqual) {
|
||||
|
@ -1286,6 +1291,7 @@ PluralRuleParser::checkSyntax(UErrorCode &status)
|
|||
type == tVariableF ||
|
||||
type == tVariableT ||
|
||||
type == tVariableE ||
|
||||
type == tVariableC ||
|
||||
type == tVariableV ||
|
||||
type == tAt)) {
|
||||
status = U_UNEXPECTED_TOKEN;
|
||||
|
@ -1318,6 +1324,7 @@ PluralRuleParser::checkSyntax(UErrorCode &status)
|
|||
type != tVariableF &&
|
||||
type != tVariableT &&
|
||||
type != tVariableE &&
|
||||
type != tVariableC &&
|
||||
type != tVariableV) {
|
||||
status = U_UNEXPECTED_TOKEN;
|
||||
}
|
||||
|
@ -1497,6 +1504,8 @@ PluralRuleParser::getKeyType(const UnicodeString &token, tokenType keyType)
|
|||
keyType = tVariableT;
|
||||
} else if (0 == token.compare(PK_VAR_E, 1)) {
|
||||
keyType = tVariableE;
|
||||
} else if (0 == token.compare(PK_VAR_C, 1)) {
|
||||
keyType = tVariableC;
|
||||
} else if (0 == token.compare(PK_VAR_V, 1)) {
|
||||
keyType = tVariableV;
|
||||
} else if (0 == token.compare(PK_IS, 2)) {
|
||||
|
@ -1596,11 +1605,17 @@ PluralOperand tokenTypeToPluralOperand(tokenType tt) {
|
|||
return PLURAL_OPERAND_T;
|
||||
case tVariableE:
|
||||
return PLURAL_OPERAND_E;
|
||||
case tVariableC:
|
||||
return PLURAL_OPERAND_E;
|
||||
default:
|
||||
UPRV_UNREACHABLE; // unexpected.
|
||||
}
|
||||
}
|
||||
|
||||
FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f, int32_t e, int32_t c) {
|
||||
init(n, v, f, e, c);
|
||||
}
|
||||
|
||||
FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f, int32_t e) {
|
||||
init(n, v, f, e);
|
||||
// check values. TODO make into unit test.
|
||||
|
@ -1642,16 +1657,30 @@ FixedDecimal::FixedDecimal() {
|
|||
FixedDecimal::FixedDecimal(const UnicodeString &num, UErrorCode &status) {
|
||||
CharString cs;
|
||||
int32_t parsedExponent = 0;
|
||||
int32_t parsedCompactExponent = 0;
|
||||
|
||||
int32_t exponentIdx = num.indexOf(u'e');
|
||||
if (exponentIdx < 0) {
|
||||
exponentIdx = num.indexOf(u'E');
|
||||
}
|
||||
int32_t compactExponentIdx = num.indexOf(u'c');
|
||||
if (compactExponentIdx < 0) {
|
||||
compactExponentIdx = num.indexOf(u'C');
|
||||
}
|
||||
|
||||
if (exponentIdx >= 0) {
|
||||
cs.appendInvariantChars(num.tempSubString(0, exponentIdx), status);
|
||||
int32_t expSubstrStart = exponentIdx + 1;
|
||||
parsedExponent = ICU_Utility::parseAsciiInteger(num, expSubstrStart);
|
||||
}
|
||||
else if (compactExponentIdx >= 0) {
|
||||
cs.appendInvariantChars(num.tempSubString(0, compactExponentIdx), status);
|
||||
int32_t expSubstrStart = compactExponentIdx + 1;
|
||||
parsedCompactExponent = ICU_Utility::parseAsciiInteger(num, expSubstrStart);
|
||||
|
||||
parsedExponent = parsedCompactExponent;
|
||||
exponentIdx = compactExponentIdx;
|
||||
}
|
||||
else {
|
||||
cs.appendInvariantChars(num, status);
|
||||
}
|
||||
|
@ -1706,13 +1735,20 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) {
|
|||
init(n, v, f, exponent);
|
||||
}
|
||||
|
||||
|
||||
void FixedDecimal::init(double n, int32_t v, int64_t f, int32_t e) {
|
||||
// Currently, `c` is an alias for `e`
|
||||
init(n, v, f, e, e);
|
||||
}
|
||||
|
||||
void FixedDecimal::init(double n, int32_t v, int64_t f, int32_t e, int32_t c) {
|
||||
isNegative = n < 0.0;
|
||||
source = fabs(n);
|
||||
_isNaN = uprv_isNaN(source);
|
||||
_isInfinite = uprv_isInfinite(source);
|
||||
exponent = e;
|
||||
if (exponent == 0) {
|
||||
exponent = c;
|
||||
}
|
||||
if (_isNaN || _isInfinite) {
|
||||
v = 0;
|
||||
f = 0;
|
||||
|
@ -1843,6 +1879,7 @@ double FixedDecimal::getPluralOperand(PluralOperand operand) const {
|
|||
case PLURAL_OPERAND_T: return static_cast<double>(decimalDigitsWithoutTrailingZeros);
|
||||
case PLURAL_OPERAND_V: return visibleDecimalDigitCount;
|
||||
case PLURAL_OPERAND_E: return exponent;
|
||||
case PLURAL_OPERAND_C: return exponent;
|
||||
default:
|
||||
UPRV_UNREACHABLE; // unexpected.
|
||||
}
|
||||
|
@ -1876,12 +1913,12 @@ bool FixedDecimal::operator==(const FixedDecimal &other) const {
|
|||
UnicodeString FixedDecimal::toString() const {
|
||||
char pattern[15];
|
||||
char buffer[20];
|
||||
if (exponent == 0) {
|
||||
snprintf(pattern, sizeof(pattern), "%%.%df", visibleDecimalDigitCount);
|
||||
snprintf(buffer, sizeof(buffer), pattern, source);
|
||||
} else {
|
||||
if (exponent != 0) {
|
||||
snprintf(pattern, sizeof(pattern), "%%.%dfe%%d", visibleDecimalDigitCount);
|
||||
snprintf(buffer, sizeof(buffer), pattern, source, exponent);
|
||||
} else {
|
||||
snprintf(pattern, sizeof(pattern), "%%.%df", visibleDecimalDigitCount);
|
||||
snprintf(buffer, sizeof(buffer), pattern, source);
|
||||
}
|
||||
return UnicodeString(buffer, -1, US_INV);
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ enum tokenType {
|
|||
tVariableV,
|
||||
tVariableT,
|
||||
tVariableE,
|
||||
tVariableC,
|
||||
tDecimal,
|
||||
tInteger,
|
||||
tEOF
|
||||
|
@ -222,11 +223,20 @@ enum PluralOperand {
|
|||
PLURAL_OPERAND_W,
|
||||
|
||||
/**
|
||||
* Suppressed exponent for compact notation (exponent needed in
|
||||
* scientific notation with compact notation to approximate i).
|
||||
* Suppressed exponent for scientific notation (exponent needed in
|
||||
* scientific notation to approximate i).
|
||||
*/
|
||||
PLURAL_OPERAND_E,
|
||||
|
||||
/**
|
||||
* This operand is currently treated as an alias for `PLURAL_OPERAND_E`.
|
||||
* In the future, it will represent:
|
||||
*
|
||||
* Suppressed exponent for compact notation (exponent needed in
|
||||
* compact notation to approximate i).
|
||||
*/
|
||||
PLURAL_OPERAND_C,
|
||||
|
||||
/**
|
||||
* THIS OPERAND IS DEPRECATED AND HAS BEEN REMOVED FROM THE SPEC.
|
||||
*
|
||||
|
@ -280,8 +290,10 @@ class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject {
|
|||
* @param n the number, e.g. 12.345
|
||||
* @param v The number of visible fraction digits, e.g. 3
|
||||
* @param f The fraction digits, e.g. 345
|
||||
* @param e The exponent, e.g. 7 in 1.2e7 (for compact/scientific)
|
||||
* @param e The exponent, e.g. 7 in 1.2e7, for scientific notation
|
||||
* @param c Currently: an alias for param `e`.
|
||||
*/
|
||||
FixedDecimal(double n, int32_t v, int64_t f, int32_t e, int32_t c);
|
||||
FixedDecimal(double n, int32_t v, int64_t f, int32_t e);
|
||||
FixedDecimal(double n, int32_t v, int64_t f);
|
||||
FixedDecimal(double n, int32_t);
|
||||
|
@ -302,6 +314,7 @@ class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject {
|
|||
|
||||
int32_t getVisibleFractionDigitCount() const;
|
||||
|
||||
void init(double n, int32_t v, int64_t f, int32_t e, int32_t c);
|
||||
void init(double n, int32_t v, int64_t f, int32_t e);
|
||||
void init(double n, int32_t v, int64_t f);
|
||||
void init(double n);
|
||||
|
|
|
@ -201,7 +201,7 @@ class DecimalQuantityTest : public IntlTest {
|
|||
void testToDouble();
|
||||
void testMaxDigits();
|
||||
void testNickelRounding();
|
||||
void testCompactDecimalSuppressedExponent();
|
||||
void testScientificAndCompactSuppressedExponent();
|
||||
void testSuppressedExponentUnchangedByInitialScaling();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
|
||||
|
|
|
@ -30,7 +30,7 @@ void DecimalQuantityTest::runIndexedTest(int32_t index, UBool exec, const char *
|
|||
TESTCASE_AUTO(testToDouble);
|
||||
TESTCASE_AUTO(testMaxDigits);
|
||||
TESTCASE_AUTO(testNickelRounding);
|
||||
TESTCASE_AUTO(testCompactDecimalSuppressedExponent);
|
||||
TESTCASE_AUTO(testScientificAndCompactSuppressedExponent);
|
||||
TESTCASE_AUTO(testSuppressedExponentUnchangedByInitialScaling);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
@ -478,8 +478,8 @@ void DecimalQuantityTest::testNickelRounding() {
|
|||
status.expectErrorAndReset(U_FORMAT_INEXACT_ERROR);
|
||||
}
|
||||
|
||||
void DecimalQuantityTest::testCompactDecimalSuppressedExponent() {
|
||||
IcuTestErrorCode status(*this, "testCompactDecimalSuppressedExponent");
|
||||
void DecimalQuantityTest::testScientificAndCompactSuppressedExponent() {
|
||||
IcuTestErrorCode status(*this, "testScientificAndCompactSuppressedExponent");
|
||||
Locale ulocale("fr-FR");
|
||||
|
||||
struct TestCase {
|
||||
|
@ -489,53 +489,56 @@ void DecimalQuantityTest::testCompactDecimalSuppressedExponent() {
|
|||
int64_t expectedLong;
|
||||
double expectedDouble;
|
||||
const char16_t* expectedPlainString;
|
||||
int32_t expectedSuppressedExponent;
|
||||
int32_t expectedSuppressedScientificExponent;
|
||||
int32_t expectedSuppressedCompactExponent;
|
||||
} cases[] = {
|
||||
// unlocalized formatter skeleton, input, string output, long output, double output, BigDecimal output, plain string, suppressed exponent
|
||||
{u"", 123456789, u"123 456 789", 123456789L, 123456789.0, u"123456789", 0},
|
||||
{u"compact-long", 123456789, u"123 millions", 123000000L, 123000000.0, u"123000000", 6},
|
||||
{u"compact-short", 123456789, u"123 M", 123000000L, 123000000.0, u"123000000", 6},
|
||||
{u"scientific", 123456789, u"1,234568E8", 123456800L, 123456800.0, u"123456800", 8},
|
||||
// unlocalized formatter skeleton, input, string output, long output,
|
||||
// double output, BigDecimal output, plain string,
|
||||
// suppressed scientific exponent, suppressed compact exponent
|
||||
{u"", 123456789, u"123 456 789", 123456789L, 123456789.0, u"123456789", 0, 0},
|
||||
{u"compact-long", 123456789, u"123 millions", 123000000L, 123000000.0, u"123000000", 6, 6},
|
||||
{u"compact-short", 123456789, u"123 M", 123000000L, 123000000.0, u"123000000", 6, 6},
|
||||
{u"scientific", 123456789, u"1,234568E8", 123456800L, 123456800.0, u"123456800", 8, 8},
|
||||
|
||||
{u"", 1234567, u"1 234 567", 1234567L, 1234567.0, u"1234567", 0},
|
||||
{u"compact-long", 1234567, u"1,2 million", 1200000L, 1200000.0, u"1200000", 6},
|
||||
{u"compact-short", 1234567, u"1,2 M", 1200000L, 1200000.0, u"1200000", 6},
|
||||
{u"scientific", 1234567, u"1,234567E6", 1234567L, 1234567.0, u"1234567", 6},
|
||||
{u"", 1234567, u"1 234 567", 1234567L, 1234567.0, u"1234567", 0, 0},
|
||||
{u"compact-long", 1234567, u"1,2 million", 1200000L, 1200000.0, u"1200000", 6, 6},
|
||||
{u"compact-short", 1234567, u"1,2 M", 1200000L, 1200000.0, u"1200000", 6, 6},
|
||||
{u"scientific", 1234567, u"1,234567E6", 1234567L, 1234567.0, u"1234567", 6, 6},
|
||||
|
||||
{u"", 123456, u"123 456", 123456L, 123456.0, u"123456", 0},
|
||||
{u"compact-long", 123456, u"123 mille", 123000L, 123000.0, u"123000", 3},
|
||||
{u"compact-short", 123456, u"123 k", 123000L, 123000.0, u"123000", 3},
|
||||
{u"scientific", 123456, u"1,23456E5", 123456L, 123456.0, u"123456", 5},
|
||||
{u"", 123456, u"123 456", 123456L, 123456.0, u"123456", 0, 0},
|
||||
{u"compact-long", 123456, u"123 mille", 123000L, 123000.0, u"123000", 3, 3},
|
||||
{u"compact-short", 123456, u"123 k", 123000L, 123000.0, u"123000", 3, 3},
|
||||
{u"scientific", 123456, u"1,23456E5", 123456L, 123456.0, u"123456", 5, 5},
|
||||
|
||||
{u"", 123, u"123", 123L, 123.0, u"123", 0},
|
||||
{u"compact-long", 123, u"123", 123L, 123.0, u"123", 0},
|
||||
{u"compact-short", 123, u"123", 123L, 123.0, u"123", 0},
|
||||
{u"scientific", 123, u"1,23E2", 123L, 123.0, u"123", 2},
|
||||
{u"", 123, u"123", 123L, 123.0, u"123", 0, 0},
|
||||
{u"compact-long", 123, u"123", 123L, 123.0, u"123", 0, 0},
|
||||
{u"compact-short", 123, u"123", 123L, 123.0, u"123", 0, 0},
|
||||
{u"scientific", 123, u"1,23E2", 123L, 123.0, u"123", 2, 2},
|
||||
|
||||
{u"", 1.2, u"1,2", 1L, 1.2, u"1.2", 0},
|
||||
{u"compact-long", 1.2, u"1,2", 1L, 1.2, u"1.2", 0},
|
||||
{u"compact-short", 1.2, u"1,2", 1L, 1.2, u"1.2", 0},
|
||||
{u"scientific", 1.2, u"1,2E0", 1L, 1.2, u"1.2", 0},
|
||||
{u"", 1.2, u"1,2", 1L, 1.2, u"1.2", 0, 0},
|
||||
{u"compact-long", 1.2, u"1,2", 1L, 1.2, u"1.2", 0, 0},
|
||||
{u"compact-short", 1.2, u"1,2", 1L, 1.2, u"1.2", 0, 0},
|
||||
{u"scientific", 1.2, u"1,2E0", 1L, 1.2, u"1.2", 0, 0},
|
||||
|
||||
{u"", 0.12, u"0,12", 0L, 0.12, u"0.12", 0},
|
||||
{u"compact-long", 0.12, u"0,12", 0L, 0.12, u"0.12", 0},
|
||||
{u"compact-short", 0.12, u"0,12", 0L, 0.12, u"0.12", 0},
|
||||
{u"scientific", 0.12, u"1,2E-1", 0L, 0.12, u"0.12", -1},
|
||||
{u"", 0.12, u"0,12", 0L, 0.12, u"0.12", 0, 0},
|
||||
{u"compact-long", 0.12, u"0,12", 0L, 0.12, u"0.12", 0, 0},
|
||||
{u"compact-short", 0.12, u"0,12", 0L, 0.12, u"0.12", 0, 0},
|
||||
{u"scientific", 0.12, u"1,2E-1", 0L, 0.12, u"0.12", -1, -1},
|
||||
|
||||
{u"", 0.012, u"0,012", 0L, 0.012, u"0.012", 0},
|
||||
{u"compact-long", 0.012, u"0,012", 0L, 0.012, u"0.012", 0},
|
||||
{u"compact-short", 0.012, u"0,012", 0L, 0.012, u"0.012", 0},
|
||||
{u"scientific", 0.012, u"1,2E-2", 0L, 0.012, u"0.012", -2},
|
||||
{u"", 0.012, u"0,012", 0L, 0.012, u"0.012", 0, 0},
|
||||
{u"compact-long", 0.012, u"0,012", 0L, 0.012, u"0.012", 0, 0},
|
||||
{u"compact-short", 0.012, u"0,012", 0L, 0.012, u"0.012", 0, 0},
|
||||
{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},
|
||||
{u"compact-long", 999.9, u"1 millier", 1000L, 1000.0, u"1000", 3},
|
||||
{u"compact-short", 999.9, u"1 k", 1000L, 1000.0, u"1000", 3},
|
||||
{u"scientific", 999.9, u"9,999E2", 999L, 999.9, u"999.9", 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-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},
|
||||
{u"compact-long", 1000.0, u"1 millier", 1000L, 1000.0, u"1000", 3},
|
||||
{u"compact-short", 1000.0, u"1 k", 1000L, 1000.0, u"1000", 3},
|
||||
{u"scientific", 1000.0, u"1E3", 1000L, 1000.0, u"1000", 3},
|
||||
{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-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},
|
||||
};
|
||||
for (const auto& cas : cases) {
|
||||
// test the helper methods used to compute plural operand values
|
||||
|
@ -550,18 +553,19 @@ void DecimalQuantityTest::testCompactDecimalSuppressedExponent() {
|
|||
int64_t actualLong = dq.toLong();
|
||||
double actualDouble = dq.toDouble();
|
||||
UnicodeString actualPlainString = dq.toPlainString();
|
||||
int32_t actualSuppressedExponent = dq.getExponent();
|
||||
int32_t actualSuppressedScientificExponent = dq.getExponent();
|
||||
int32_t actualSuppressedCompactExponent = dq.getExponent();
|
||||
|
||||
assertEquals(
|
||||
u"formatted number " + cas.skeleton + u" toString: " + cas.input,
|
||||
cas.expectedString,
|
||||
actualString);
|
||||
assertEquals(
|
||||
u"compact decimal " + cas.skeleton + u" toLong: " + cas.input,
|
||||
u"formatted number " + cas.skeleton + u" toLong: " + cas.input,
|
||||
cas.expectedLong,
|
||||
actualLong);
|
||||
assertDoubleEquals(
|
||||
u"compact decimal " + cas.skeleton + u" toDouble: " + cas.input,
|
||||
u"formatted number " + cas.skeleton + u" toDouble: " + cas.input,
|
||||
cas.expectedDouble,
|
||||
actualDouble);
|
||||
assertEquals(
|
||||
|
@ -569,36 +573,46 @@ void DecimalQuantityTest::testCompactDecimalSuppressedExponent() {
|
|||
cas.expectedPlainString,
|
||||
actualPlainString);
|
||||
assertEquals(
|
||||
u"compact decimal " + cas.skeleton + u" suppressed exponent: " + cas.input,
|
||||
cas.expectedSuppressedExponent,
|
||||
actualSuppressedExponent);
|
||||
u"formatted number " + cas.skeleton + u" suppressed scientific exponent: " + cas.input,
|
||||
cas.expectedSuppressedScientificExponent,
|
||||
actualSuppressedScientificExponent);
|
||||
assertEquals(
|
||||
u"formatted number " + cas.skeleton + u" suppressed compact exponent: " + cas.input,
|
||||
cas.expectedSuppressedCompactExponent,
|
||||
actualSuppressedCompactExponent);
|
||||
|
||||
// test the actual computed values of the plural operands
|
||||
|
||||
double expectedNOperand = cas.expectedDouble;
|
||||
double expectedIOperand = cas.expectedLong;
|
||||
double expectedEOperand = cas.expectedSuppressedExponent;
|
||||
double expectedEOperand = cas.expectedSuppressedScientificExponent;
|
||||
double expectedCOperand = cas.expectedSuppressedCompactExponent;
|
||||
double actualNOperand = dq.getPluralOperand(PLURAL_OPERAND_N);
|
||||
double actualIOperand = dq.getPluralOperand(PLURAL_OPERAND_I);
|
||||
double actualEOperand = dq.getPluralOperand(PLURAL_OPERAND_E);
|
||||
double actualCOperand = dq.getPluralOperand(PLURAL_OPERAND_C);
|
||||
|
||||
assertDoubleEquals(
|
||||
u"compact decimal " + cas.skeleton + u" n operand: " + cas.input,
|
||||
u"formatted number " + cas.skeleton + u" n operand: " + cas.input,
|
||||
expectedNOperand,
|
||||
actualNOperand);
|
||||
assertDoubleEquals(
|
||||
u"compact decimal " + cas.skeleton + u" i operand: " + cas.input,
|
||||
u"formatted number " + cas.skeleton + u" i operand: " + cas.input,
|
||||
expectedIOperand,
|
||||
actualIOperand);
|
||||
assertDoubleEquals(
|
||||
u"compact decimal " + cas.skeleton + " e operand: " + cas.input,
|
||||
u"formatted number " + cas.skeleton + " e operand: " + cas.input,
|
||||
expectedEOperand,
|
||||
actualEOperand);
|
||||
assertDoubleEquals(
|
||||
u"formatted number " + cas.skeleton + " c operand: " + cas.input,
|
||||
expectedCOperand,
|
||||
actualCOperand);
|
||||
}
|
||||
}
|
||||
|
||||
void DecimalQuantityTest::testSuppressedExponentUnchangedByInitialScaling() {
|
||||
IcuTestErrorCode status(*this, "testCompactDecimalSuppressedExponent");
|
||||
IcuTestErrorCode status(*this, "testSuppressedExponentUnchangedByInitialScaling");
|
||||
Locale ulocale("fr-FR");
|
||||
LocalizedNumberFormatter withLocale = NumberFormatter::withLocale(ulocale);
|
||||
LocalizedNumberFormatter compactLong =
|
||||
|
@ -612,20 +626,22 @@ void DecimalQuantityTest::testSuppressedExponentUnchangedByInitialScaling() {
|
|||
double expectedNOperand;
|
||||
double expectedIOperand;
|
||||
double expectedEOperand;
|
||||
double expectedCOperand;
|
||||
} cases[] = {
|
||||
// input, compact long string output,
|
||||
// compact n operand, compact i operand, compact e operand
|
||||
{123456789, "123 millions", 123000000.0, 123000000.0, 6.0},
|
||||
{1234567, "1,2 million", 1200000.0, 1200000.0, 6.0},
|
||||
{123456, "123 mille", 123000.0, 123000.0, 3.0},
|
||||
{123, "123", 123.0, 123.0, 0.0},
|
||||
// compact n operand, compact i operand, compact e operand,
|
||||
// compact c operand
|
||||
{123456789, "123 millions", 123000000.0, 123000000.0, 6.0, 6.0},
|
||||
{1234567, "1,2 million", 1200000.0, 1200000.0, 6.0, 6.0},
|
||||
{123456, "123 mille", 123000.0, 123000.0, 3.0, 3.0},
|
||||
{123, "123", 123.0, 123.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
for (const auto& cas : cases) {
|
||||
FormattedNumber fnCompactScaled = compactScaled.formatInt(cas.input, status);
|
||||
DecimalQuantity dqCompactScaled;
|
||||
fnCompactScaled.getDecimalQuantity(dqCompactScaled, status);
|
||||
double compactScaledEOperand = dqCompactScaled.getPluralOperand(PLURAL_OPERAND_E);
|
||||
double compactScaledCOperand = dqCompactScaled.getPluralOperand(PLURAL_OPERAND_C);
|
||||
|
||||
FormattedNumber fnCompact = compactLong.formatInt(cas.input, status);
|
||||
DecimalQuantity dqCompact;
|
||||
|
@ -634,6 +650,7 @@ void DecimalQuantityTest::testSuppressedExponentUnchangedByInitialScaling() {
|
|||
double compactNOperand = dqCompact.getPluralOperand(PLURAL_OPERAND_N);
|
||||
double compactIOperand = dqCompact.getPluralOperand(PLURAL_OPERAND_I);
|
||||
double compactEOperand = dqCompact.getPluralOperand(PLURAL_OPERAND_E);
|
||||
double compactCOperand = dqCompact.getPluralOperand(PLURAL_OPERAND_C);
|
||||
assertEquals(
|
||||
u"formatted number " + Int64ToUnicodeString(cas.input) + " compactLong toString: ",
|
||||
cas.expectedString,
|
||||
|
@ -650,14 +667,18 @@ void DecimalQuantityTest::testSuppressedExponentUnchangedByInitialScaling() {
|
|||
u"compact decimal " + DoubleToUnicodeString(cas.input) + ", e operand vs. expected",
|
||||
cas.expectedEOperand,
|
||||
compactEOperand);
|
||||
assertDoubleEquals(
|
||||
u"compact decimal " + DoubleToUnicodeString(cas.input) + ", c operand vs. expected",
|
||||
cas.expectedCOperand,
|
||||
compactCOperand);
|
||||
|
||||
// By scaling by 10^3 in a locale that has words / compact notation
|
||||
// based on powers of 10^3, we guarantee that the suppressed
|
||||
// exponent will differ by 3.
|
||||
assertDoubleEquals(
|
||||
u"decimal " + DoubleToUnicodeString(cas.input) + ", e operand for compact vs. compact scaled",
|
||||
compactEOperand + 3,
|
||||
compactScaledEOperand);
|
||||
u"decimal " + DoubleToUnicodeString(cas.input) + ", c operand for compact vs. compact scaled",
|
||||
compactCOperand + 3,
|
||||
compactScaledCOperand);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,8 +52,10 @@ void PluralRulesTest::runIndexedTest( int32_t index, UBool exec, const char* &na
|
|||
TESTCASE_AUTO(testGetSamples);
|
||||
TESTCASE_AUTO(testGetFixedDecimalSamples);
|
||||
TESTCASE_AUTO(testSamplesWithExponent);
|
||||
TESTCASE_AUTO(testSamplesWithCompactNotation);
|
||||
TESTCASE_AUTO(testWithin);
|
||||
TESTCASE_AUTO(testGetAllKeywordValues);
|
||||
TESTCASE_AUTO(testScientificPluralKeyword);
|
||||
TESTCASE_AUTO(testCompactDecimalPluralKeyword);
|
||||
TESTCASE_AUTO(testOrdinal);
|
||||
TESTCASE_AUTO(testSelect);
|
||||
|
@ -404,7 +406,7 @@ void PluralRulesTest::testGetSamples() {
|
|||
double values[1000];
|
||||
for (int32_t i = 0; U_SUCCESS(status) && i < numLocales; ++i) {
|
||||
if (uprv_strcmp(locales[i].getLanguage(), "fr") == 0 &&
|
||||
logKnownIssue("21299", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
|
||||
logKnownIssue("21322", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
|
||||
continue;
|
||||
}
|
||||
LocalPointer<PluralRules> rules(PluralRules::forLocale(locales[i], status));
|
||||
|
@ -465,7 +467,7 @@ void PluralRulesTest::testGetFixedDecimalSamples() {
|
|||
FixedDecimal values[1000];
|
||||
for (int32_t i = 0; U_SUCCESS(status) && i < numLocales; ++i) {
|
||||
if (uprv_strcmp(locales[i].getLanguage(), "fr") == 0 &&
|
||||
logKnownIssue("21299", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
|
||||
logKnownIssue("21322", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
|
||||
continue;
|
||||
}
|
||||
LocalPointer<PluralRules> rules(PluralRules::forLocale(locales[i], status));
|
||||
|
@ -551,6 +553,44 @@ void PluralRulesTest::testSamplesWithExponent() {
|
|||
checkNewSamples(description2, test2, u"other", u"@decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …", FixedDecimal(2.0, 1));
|
||||
}
|
||||
|
||||
|
||||
void PluralRulesTest::testSamplesWithCompactNotation() {
|
||||
// integer samples
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString description(
|
||||
u"one: i = 0,1 @integer 0, 1, 1c5 @decimal 0.0~1.5, 1.1c5; "
|
||||
u"many: c = 0 and i != 0 and i % 1000000 = 0 and v = 0 or c != 0..5"
|
||||
u" @integer 1000000, 2c6, 3c6, 4c6, 5c6, 6c6, 7c6, … @decimal 2.1c6, 3.1c6, 4.1c6, 5.1c6, 6.1c6, 7.1c6, …; "
|
||||
u"other: @integer 2~17, 100, 1000, 10000, 100000, 2c5, 3c5, 4c5, 5c5, 6c5, 7c5, …"
|
||||
u" @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1c5, 3.1c5, 4.1c5, 5.1c5, 6.1c5, 7.1c5, …"
|
||||
);
|
||||
LocalPointer<PluralRules> test(PluralRules::createRules(description, status));
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Couldn't create plural rules from a string using exponent notation, with error = %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
checkNewSamples(description, test, u"one", u"@integer 0, 1, 1c5", FixedDecimal(0));
|
||||
checkNewSamples(description, test, u"many", u"@integer 1000000, 2c6, 3c6, 4c6, 5c6, 6c6, 7c6, …", FixedDecimal(1000000));
|
||||
checkNewSamples(description, test, u"other", u"@integer 2~17, 100, 1000, 10000, 100000, 2c5, 3c5, 4c5, 5c5, 6c5, 7c5, …", FixedDecimal(2));
|
||||
|
||||
// decimal samples
|
||||
status = U_ZERO_ERROR;
|
||||
UnicodeString description2(
|
||||
u"one: i = 0,1 @decimal 0.0~1.5, 1.1c5; "
|
||||
u"many: c = 0 and i != 0 and i % 1000000 = 0 and v = 0 or c != 0..5"
|
||||
u" @decimal 2.1c6, 3.1c6, 4.1c6, 5.1c6, 6.1c6, 7.1c6, …; "
|
||||
u"other: @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1c5, 3.1c5, 4.1c5, 5.1c5, 6.1c5, 7.1c5, …"
|
||||
);
|
||||
LocalPointer<PluralRules> test2(PluralRules::createRules(description2, status));
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Couldn't create plural rules from a string using exponent notation, with error = %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
checkNewSamples(description2, test2, u"one", u"@decimal 0.0~1.5, 1.1c5", FixedDecimal(0, 1));
|
||||
checkNewSamples(description2, test2, u"many", u"@decimal 2.1c6, 3.1c6, 4.1c6, 5.1c6, 6.1c6, 7.1c6, …", FixedDecimal::createWithExponent(2.1, 1, 6));
|
||||
checkNewSamples(description2, test2, u"other", u"@decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1c5, 3.1c5, 4.1c5, 5.1c5, 6.1c5, 7.1c5, …", FixedDecimal(2.0, 1));
|
||||
}
|
||||
|
||||
void PluralRulesTest::checkNewSamples(
|
||||
UnicodeString description,
|
||||
const LocalPointer<PluralRules> &test,
|
||||
|
@ -727,13 +767,77 @@ PluralRulesTest::testGetAllKeywordValues() {
|
|||
}
|
||||
}
|
||||
|
||||
// For the time being, the compact notation exponent operand `c` is an alias
|
||||
// for the scientific exponent operand `e` and compact notation.
|
||||
void
|
||||
PluralRulesTest::testScientificPluralKeyword() {
|
||||
IcuTestErrorCode errorCode(*this, "testScientificPluralKeyword");
|
||||
|
||||
LocalPointer<PluralRules> rules(PluralRules::createRules(
|
||||
u"one: i = 0,1 @integer 0, 1 @decimal 0.0~1.5; "
|
||||
u"many: e = 0 and i % 1000000 = 0 and v = 0 or e != 0 .. 5; "
|
||||
u"other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, "
|
||||
u" @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …", errorCode));
|
||||
|
||||
if (U_FAILURE(errorCode)) {
|
||||
errln("Couldn't instantiate plurals rules from string, with error = %s", u_errorName(errorCode));
|
||||
return;
|
||||
}
|
||||
|
||||
const char* localeName = "fr-FR";
|
||||
Locale locale = Locale::createFromName(localeName);
|
||||
|
||||
struct TestCase {
|
||||
const char16_t* skeleton;
|
||||
const int input;
|
||||
const char16_t* expectedFormattedOutput;
|
||||
const char16_t* expectedPluralRuleKeyword;
|
||||
} cases[] = {
|
||||
// unlocalized formatter skeleton, input, string output, plural rule keyword
|
||||
{u"", 0, u"0", u"one"},
|
||||
{u"scientific", 0, u"0", u"one"},
|
||||
|
||||
{u"", 1, u"1", u"one"},
|
||||
{u"scientific", 1, u"1", u"one"},
|
||||
|
||||
{u"", 2, u"2", u"other"},
|
||||
{u"scientific", 2, u"2", u"other"},
|
||||
|
||||
{u"", 1000000, u"1 000 000", u"many"},
|
||||
{u"scientific", 1000000, u"1 million", u"many"},
|
||||
|
||||
{u"", 1000001, u"1 000 001", u"other"},
|
||||
{u"scientific", 1000001, u"1 million", u"many"},
|
||||
|
||||
{u"", 120000, u"1 200 000", u"other"},
|
||||
{u"scientific", 1200000, u"1,2 millions", u"many"},
|
||||
|
||||
{u"", 1200001, u"1 200 001", u"other"},
|
||||
{u"scientific", 1200001, u"1,2 millions", u"many"},
|
||||
|
||||
{u"", 2000000, u"2 000 000", u"many"},
|
||||
{u"scientific", 2000000, u"2 millions", u"many"},
|
||||
};
|
||||
for (const auto& cas : cases) {
|
||||
const char16_t* skeleton = cas.skeleton;
|
||||
const int input = cas.input;
|
||||
const char16_t* expectedPluralRuleKeyword = cas.expectedPluralRuleKeyword;
|
||||
|
||||
UnicodeString actualPluralRuleKeyword =
|
||||
getPluralKeyword(rules, locale, input, skeleton);
|
||||
|
||||
UnicodeString message(UnicodeString(localeName) + u" " + DoubleToUnicodeString(input));
|
||||
assertEquals(message, expectedPluralRuleKeyword, actualPluralRuleKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluralRulesTest::testCompactDecimalPluralKeyword() {
|
||||
IcuTestErrorCode errorCode(*this, "testCompactDecimalPluralKeyword");
|
||||
|
||||
LocalPointer<PluralRules> rules(PluralRules::createRules(
|
||||
u"one: i = 0,1 @integer 0, 1 @decimal 0.0~1.5; "
|
||||
u"many: e = 0 and i % 1000000 = 0 and v = 0 or e != 0 .. 5; "
|
||||
u"many: c = 0 and i % 1000000 = 0 and v = 0 or c != 0 .. 5; "
|
||||
u"other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, "
|
||||
u" @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …", errorCode));
|
||||
|
||||
|
|
|
@ -32,9 +32,11 @@ private:
|
|||
void testGetSamples();
|
||||
void testGetFixedDecimalSamples();
|
||||
void testSamplesWithExponent();
|
||||
void testSamplesWithCompactNotation();
|
||||
void testWithin();
|
||||
void testGetAllKeywordValues();
|
||||
void testCompactDecimalPluralKeyword();
|
||||
void testScientificPluralKeyword();
|
||||
void testOrdinal();
|
||||
void testSelect();
|
||||
void testSelectRange();
|
||||
|
|
|
@ -265,6 +265,9 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity {
|
|||
return fractionCountWithoutTrailingZeros();
|
||||
case e:
|
||||
return getExponent();
|
||||
case c:
|
||||
// Plural operand `c` is currently an alias for `e`.
|
||||
return getExponent();
|
||||
default:
|
||||
return Math.abs(toDouble());
|
||||
}
|
||||
|
|
|
@ -481,8 +481,8 @@ public class PluralRules implements Serializable {
|
|||
w,
|
||||
|
||||
/**
|
||||
* Suppressed exponent for compact notation (exponent needed in
|
||||
* scientific notation with compact notation to approximate i).
|
||||
* Suppressed exponent for scientific notation (exponent needed in
|
||||
* scientific notation to approximate i).
|
||||
*
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -490,6 +490,19 @@ public class PluralRules implements Serializable {
|
|||
@Deprecated
|
||||
e,
|
||||
|
||||
/**
|
||||
* This operand is currently treated as an alias for `PLURAL_OPERAND_E`.
|
||||
* In the future, it will represent:
|
||||
*
|
||||
* Suppressed exponent for compact notation (exponent needed in
|
||||
* compact notation to approximate i).
|
||||
*
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
c,
|
||||
|
||||
/**
|
||||
* THIS OPERAND IS DEPRECATED AND HAS BEEN REMOVED FROM THE SPEC.
|
||||
*
|
||||
|
@ -657,10 +670,11 @@ public class PluralRules implements Serializable {
|
|||
* @param v number of digits to the right of the decimal place. e.g 1.00 = 2 25. = 0
|
||||
* @param f Corresponds to f in the plural rules grammar.
|
||||
* The digits to the right of the decimal place as an integer. e.g 1.10 = 10
|
||||
* @param e Suppressed exponent for scientific and compact notation
|
||||
* @param e Suppressed exponent for scientific notation
|
||||
* @param c Currently: an alias for param `e`
|
||||
*/
|
||||
@Deprecated
|
||||
public FixedDecimal(double n, int v, long f, int e) {
|
||||
public FixedDecimal(double n, int v, long f, int e, int c) {
|
||||
isNegative = n < 0;
|
||||
source = isNegative ? -n : n;
|
||||
visibleDecimalDigitCount = v;
|
||||
|
@ -668,7 +682,11 @@ public class PluralRules implements Serializable {
|
|||
integerValue = n > MAX
|
||||
? MAX
|
||||
: (long)n;
|
||||
exponent = e;
|
||||
int initExpVal = e;
|
||||
if (initExpVal == 0) {
|
||||
initExpVal = c;
|
||||
}
|
||||
exponent = initExpVal;
|
||||
hasIntegerValue = source == integerValue;
|
||||
// check values. TODO make into unit test.
|
||||
//
|
||||
|
@ -699,6 +717,15 @@ public class PluralRules implements Serializable {
|
|||
baseFactor = (int) Math.pow(10, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
@Deprecated
|
||||
public FixedDecimal(double n, int v, long f, int e) {
|
||||
this(n, v, f, e, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal CLDR
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -848,8 +875,11 @@ public class PluralRules implements Serializable {
|
|||
*/
|
||||
@Deprecated
|
||||
private static FixedDecimal parseDecimalSampleRangeNumString(String num) {
|
||||
if (num.contains("e")) {
|
||||
if (num.contains("e") || num.contains("c")) {
|
||||
int ePos = num.lastIndexOf('e');
|
||||
if (ePos < 0) {
|
||||
ePos = num.lastIndexOf('c');
|
||||
}
|
||||
int expNumPos = ePos + 1;
|
||||
String exponentStr = num.substring(expNumPos);
|
||||
int exponent = Integer.parseInt(exponentStr);
|
||||
|
@ -890,6 +920,7 @@ public class PluralRules implements Serializable {
|
|||
case v: return visibleDecimalDigitCount;
|
||||
case w: return visibleDecimalDigitCountWithoutTrailingZeros;
|
||||
case e: return exponent;
|
||||
case c: return exponent;
|
||||
default: return source;
|
||||
}
|
||||
}
|
||||
|
@ -970,10 +1001,10 @@ public class PluralRules implements Serializable {
|
|||
@Override
|
||||
public String toString() {
|
||||
String baseString = String.format(Locale.ROOT, "%." + visibleDecimalDigitCount + "f", source);
|
||||
if (exponent == 0) {
|
||||
return baseString;
|
||||
} else {
|
||||
if (exponent != 0) {
|
||||
return baseString + "e" + exponent;
|
||||
} else {
|
||||
return baseString;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -219,6 +219,37 @@ public class PluralRulesTest extends TestFmwk {
|
|||
new FixedDecimal(2.0, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* This test is for the support of X.YcZ compactnotation of numbers in
|
||||
* the plural sample string.
|
||||
*/
|
||||
@Test
|
||||
public void testSamplesWithCompactNotation() {
|
||||
String description = "one: i = 0,1 @integer 0, 1, 1c5 @decimal 0.0~1.5, 1.1c5; "
|
||||
+ "many: c = 0 and i != 0 and i % 1000000 = 0 and v = 0 or c != 0..5"
|
||||
+ " @integer 1000000, 2c6, 3c6, 4c6, 5c6, 6c6, 7c6, … @decimal 2.1c6, 3.1c6, 4.1c6, 5.1c6, 6.1c6, 7.1c6, …; "
|
||||
+ "other: @integer 2~17, 100, 1000, 10000, 100000, 2c5, 3c5, 4c5, 5c5, 6c5, 7c5, …"
|
||||
+ " @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1c5, 3.1c5, 4.1c5, 5.1c5, 6.1c5, 7.1c5, …"
|
||||
;
|
||||
// Creating the PluralRules object means being able to parse numbers
|
||||
// like 1c5 and 1.1c5.
|
||||
// Note: Since `c` is currently an alias to `e`, the toString() of
|
||||
// FixedDecimal will return "1e5" even when input is "1c5".
|
||||
PluralRules test = PluralRules.createRules(description);
|
||||
checkNewSamples(description, test, "one", PluralRules.SampleType.INTEGER, "@integer 0, 1, 1e5", true,
|
||||
new FixedDecimal(0));
|
||||
checkNewSamples(description, test, "one", PluralRules.SampleType.DECIMAL, "@decimal 0.0~1.5, 1.1e5", true,
|
||||
new FixedDecimal(0, 1));
|
||||
checkNewSamples(description, test, "many", PluralRules.SampleType.INTEGER, "@integer 1000000, 2e6, 3e6, 4e6, 5e6, 6e6, 7e6, …", false,
|
||||
new FixedDecimal(1000000));
|
||||
checkNewSamples(description, test, "many", PluralRules.SampleType.DECIMAL, "@decimal 2.1e6, 3.1e6, 4.1e6, 5.1e6, 6.1e6, 7.1e6, …", false,
|
||||
FixedDecimal.createWithExponent(2.1, 1, 6));
|
||||
checkNewSamples(description, test, "other", PluralRules.SampleType.INTEGER, "@integer 2~17, 100, 1000, 10000, 100000, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, …", false,
|
||||
new FixedDecimal(2));
|
||||
checkNewSamples(description, test, "other", PluralRules.SampleType.DECIMAL, "@decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 2.1e5, 3.1e5, 4.1e5, 5.1e5, 6.1e5, 7.1e5, …", false,
|
||||
new FixedDecimal(2.0, 1));
|
||||
}
|
||||
|
||||
public void checkOldSamples(String description, PluralRules rules, String keyword, SampleType sampleType,
|
||||
Double... expected) {
|
||||
Collection<Double> oldSamples = rules.getSamples(keyword, sampleType);
|
||||
|
@ -713,7 +744,7 @@ public class PluralRulesTest extends TestFmwk {
|
|||
}
|
||||
for (ULocale locale : uniqueRuleSet) {
|
||||
if (locale.getLanguage().equals("fr") &&
|
||||
logKnownIssue("21299", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
|
||||
logKnownIssue("21322", "PluralRules::getSamples cannot distinguish 1e5 from 100000")) {
|
||||
continue;
|
||||
}
|
||||
PluralRules rules = factory.forLocale(locale);
|
||||
|
@ -968,12 +999,61 @@ public class PluralRulesTest extends TestFmwk {
|
|||
}
|
||||
}
|
||||
|
||||
// For the time being, the compact notation exponent operand `c` is an alias
|
||||
// for the scientific exponent operand `e` and compact notation.
|
||||
@Test
|
||||
public void testScientificPluralKeyword() {
|
||||
PluralRules rules = PluralRules.createRules("one: i = 0,1 @integer 0, 1 @decimal 0.0~1.5; many: e = 0 and i % 1000000 = 0 and v = 0 or " +
|
||||
"e != 0 .. 5; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …");
|
||||
ULocale locale = new ULocale("fr-FR");
|
||||
|
||||
Object[][] casesData = {
|
||||
// unlocalized formatter skeleton, input, string output, plural rule keyword
|
||||
{"", 0, "0", "one"},
|
||||
{"scientific", 0, "0", "one"},
|
||||
|
||||
{"", 1, "1", "one"},
|
||||
{"scientific", 1, "1", "one"},
|
||||
|
||||
{"", 2, "2", "other"},
|
||||
{"scientific", 2, "2", "other"},
|
||||
|
||||
{"", 1000000, "1 000 000", "many"},
|
||||
{"scientific", 1000000, "1 million", "many"},
|
||||
|
||||
{"", 1000001, "1 000 001", "other"},
|
||||
{"scientific", 1000001, "1 million", "many"},
|
||||
|
||||
{"", 120000, "1 200 000", "other"},
|
||||
{"scientific", 1200000, "1,2 millions", "many"},
|
||||
|
||||
{"", 1200001, "1 200 001", "other"},
|
||||
{"scientific", 1200001, "1,2 millions", "many"},
|
||||
|
||||
{"", 2000000, "2 000 000", "many"},
|
||||
{"scientific", 2000000, "2 millions", "many"},
|
||||
};
|
||||
|
||||
for (Object[] caseDatum : casesData) {
|
||||
String skeleton = (String) caseDatum[0];
|
||||
int input = (int) caseDatum[1];
|
||||
// String expectedString = (String) caseDatum[2];
|
||||
String expectPluralRuleKeyword = (String) caseDatum[3];
|
||||
|
||||
String actualPluralRuleKeyword =
|
||||
getPluralKeyword(rules, locale, input, skeleton);
|
||||
|
||||
assertEquals(
|
||||
String.format("PluralRules select %s: %d", skeleton, input),
|
||||
expectPluralRuleKeyword,
|
||||
actualPluralRuleKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompactDecimalPluralKeyword() {
|
||||
PluralRules rules = PluralRules.createRules("one: i = 0,1 @integer 0, 1 @decimal 0.0~1.5; many: e = 0 and i % 1000000 = 0 and v = 0 or " +
|
||||
"e != 0 .. 5; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …");
|
||||
PluralRules rules = PluralRules.createRules("one: i = 0,1 @integer 0, 1 @decimal 0.0~1.5; many: c = 0 and i % 1000000 = 0 and v = 0 or " +
|
||||
"c != 0 .. 5; other: @integer 2~17, 100, 1000, 10000, 100000, 1000000, @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …");
|
||||
ULocale locale = new ULocale("fr-FR");
|
||||
|
||||
Object[][] casesData = {
|
||||
|
|
|
@ -609,55 +609,57 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCompactDecimalSuppressedExponent() {
|
||||
public void testScientificAndCompactSuppressedExponent() {
|
||||
ULocale locale = new ULocale("fr-FR");
|
||||
|
||||
Object[][] casesData = {
|
||||
// unlocalized formatter skeleton, input, string output, long output, double output, BigDecimal output, plain string, suppressed exponent
|
||||
{"", 123456789, "123 456 789", 123456789L, 123456789.0, new BigDecimal("123456789"), "123456789", 0},
|
||||
{"compact-long", 123456789, "123 millions", 123000000L, 123000000.0, new BigDecimal("123000000"), "123000000", 6},
|
||||
{"compact-short", 123456789, "123 M", 123000000L, 123000000.0, new BigDecimal("123000000"), "123000000", 6},
|
||||
{"scientific", 123456789, "1,234568E8", 123456800L, 123456800.0, new BigDecimal("123456800"), "123456800", 8},
|
||||
// unlocalized formatter skeleton, input, string output, long output,
|
||||
// double output, BigDecimal output, plain string,
|
||||
// suppressed scientific exponent, suppressed compact exponent
|
||||
{"", 123456789, "123 456 789", 123456789L, 123456789.0, new BigDecimal("123456789"), "123456789", 0, 0},
|
||||
{"compact-long", 123456789, "123 millions", 123000000L, 123000000.0, new BigDecimal("123000000"), "123000000", 6, 6},
|
||||
{"compact-short", 123456789, "123 M", 123000000L, 123000000.0, new BigDecimal("123000000"), "123000000", 6, 6},
|
||||
{"scientific", 123456789, "1,234568E8", 123456800L, 123456800.0, new BigDecimal("123456800"), "123456800", 8, 8},
|
||||
|
||||
{"", 1234567, "1 234 567", 1234567L, 1234567.0, new BigDecimal("1234567"), "1234567", 0},
|
||||
{"compact-long", 1234567, "1,2 million", 1200000L, 1200000.0, new BigDecimal("1200000"), "1200000", 6},
|
||||
{"compact-short", 1234567, "1,2 M", 1200000L, 1200000.0, new BigDecimal("1200000"), "1200000", 6},
|
||||
{"scientific", 1234567, "1,234567E6", 1234567L, 1234567.0, new BigDecimal("1234567"), "1234567", 6},
|
||||
{"", 1234567, "1 234 567", 1234567L, 1234567.0, new BigDecimal("1234567"), "1234567", 0, 0},
|
||||
{"compact-long", 1234567, "1,2 million", 1200000L, 1200000.0, new BigDecimal("1200000"), "1200000", 6, 6},
|
||||
{"compact-short", 1234567, "1,2 M", 1200000L, 1200000.0, new BigDecimal("1200000"), "1200000", 6, 6},
|
||||
{"scientific", 1234567, "1,234567E6", 1234567L, 1234567.0, new BigDecimal("1234567"), "1234567", 6, 6},
|
||||
|
||||
{"", 123456, "123 456", 123456L, 123456.0, new BigDecimal("123456"), "123456", 0},
|
||||
{"compact-long", 123456, "123 mille", 123000L, 123000.0, new BigDecimal("123000"), "123000", 3},
|
||||
{"compact-short", 123456, "123 k", 123000L, 123000.0, new BigDecimal("123000"), "123000", 3},
|
||||
{"scientific", 123456, "1,23456E5", 123456L, 123456.0, new BigDecimal("123456"), "123456", 5},
|
||||
{"", 123456, "123 456", 123456L, 123456.0, new BigDecimal("123456"), "123456", 0, 0},
|
||||
{"compact-long", 123456, "123 mille", 123000L, 123000.0, new BigDecimal("123000"), "123000", 3, 3},
|
||||
{"compact-short", 123456, "123 k", 123000L, 123000.0, new BigDecimal("123000"), "123000", 3, 3},
|
||||
{"scientific", 123456, "1,23456E5", 123456L, 123456.0, new BigDecimal("123456"), "123456", 5, 5},
|
||||
|
||||
{"", 123, "123", 123L, 123.0, new BigDecimal("123"), "123", 0},
|
||||
{"compact-long", 123, "123", 123L, 123.0, new BigDecimal("123"), "123", 0},
|
||||
{"compact-short", 123, "123", 123L, 123.0, new BigDecimal("123"), "123", 0},
|
||||
{"scientific", 123, "1,23E2", 123L, 123.0, new BigDecimal("123"), "123", 2},
|
||||
{"", 123, "123", 123L, 123.0, new BigDecimal("123"), "123", 0, 0},
|
||||
{"compact-long", 123, "123", 123L, 123.0, new BigDecimal("123"), "123", 0, 0},
|
||||
{"compact-short", 123, "123", 123L, 123.0, new BigDecimal("123"), "123", 0, 0},
|
||||
{"scientific", 123, "1,23E2", 123L, 123.0, new BigDecimal("123"), "123", 2, 2},
|
||||
|
||||
{"", 1.2, "1,2", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0},
|
||||
{"compact-long", 1.2, "1,2", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0},
|
||||
{"compact-short", 1.2, "1,2", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0},
|
||||
{"scientific", 1.2, "1,2E0", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0},
|
||||
{"", 1.2, "1,2", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0, 0},
|
||||
{"compact-long", 1.2, "1,2", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0, 0},
|
||||
{"compact-short", 1.2, "1,2", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0, 0},
|
||||
{"scientific", 1.2, "1,2E0", 1L, 1.2, new BigDecimal("1.2"), "1.2", 0, 0},
|
||||
|
||||
{"", 0.12, "0,12", 0L, 0.12, new BigDecimal("0.12"), "0.12", 0},
|
||||
{"compact-long", 0.12, "0,12", 0L, 0.12, new BigDecimal("0.12"), "0.12", 0},
|
||||
{"compact-short", 0.12, "0,12", 0L, 0.12, new BigDecimal("0.12"), "0.12", 0},
|
||||
{"scientific", 0.12, "1,2E-1", 0L, 0.12, new BigDecimal("0.12"), "0.12", -1},
|
||||
{"", 0.12, "0,12", 0L, 0.12, new BigDecimal("0.12"), "0.12", 0, 0},
|
||||
{"compact-long", 0.12, "0,12", 0L, 0.12, new BigDecimal("0.12"), "0.12", 0, 0},
|
||||
{"compact-short", 0.12, "0,12", 0L, 0.12, new BigDecimal("0.12"), "0.12", 0, 0},
|
||||
{"scientific", 0.12, "1,2E-1", 0L, 0.12, new BigDecimal("0.12"), "0.12", -1, -1},
|
||||
|
||||
{"", 0.012, "0,012", 0L, 0.012, new BigDecimal("0.012"), "0.012", 0},
|
||||
{"compact-long", 0.012, "0,012", 0L, 0.012, new BigDecimal("0.012"), "0.012", 0},
|
||||
{"compact-short", 0.012, "0,012", 0L, 0.012, new BigDecimal("0.012"), "0.012", 0},
|
||||
{"scientific", 0.012, "1,2E-2", 0L, 0.012, new BigDecimal("0.012"), "0.012", -2},
|
||||
{"", 0.012, "0,012", 0L, 0.012, new BigDecimal("0.012"), "0.012", 0, 0},
|
||||
{"compact-long", 0.012, "0,012", 0L, 0.012, new BigDecimal("0.012"), "0.012", 0, 0},
|
||||
{"compact-short", 0.012, "0,012", 0L, 0.012, new BigDecimal("0.012"), "0.012", 0, 0},
|
||||
{"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},
|
||||
{"compact-long", 999.9, "1 millier", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3},
|
||||
{"compact-short", 999.9, "1 k", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3},
|
||||
{"scientific", 999.9, "9,999E2", 999L, 999.9, new BigDecimal("999.9"), "999.9", 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-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},
|
||||
{"compact-long", 1000.0, "1 millier", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3},
|
||||
{"compact-short", 1000.0, "1 k", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3},
|
||||
{"scientific", 1000.0, "1E3", 1000L, 1000.0, new BigDecimal("1000"), "1000", 3},
|
||||
{"", 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-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},
|
||||
};
|
||||
|
||||
for (Object[] caseDatum : casesData) {
|
||||
|
@ -673,7 +675,8 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
double expectedDouble = (double) caseDatum[4];
|
||||
BigDecimal expectedBigDecimal = (BigDecimal) caseDatum[5];
|
||||
String expectedPlainString = (String) caseDatum[6];
|
||||
int expectedSuppressedExponent = (int) caseDatum[7];
|
||||
int expectedSuppressedScientificExponent = (int) caseDatum[7];
|
||||
int expectedSuppressedCompactExponent = (int) caseDatum[8];
|
||||
|
||||
FormattedNumber fn = formatter.format(input);
|
||||
DecimalQuantity_DualStorageBCD dq = (DecimalQuantity_DualStorageBCD)
|
||||
|
@ -683,22 +686,23 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
double actualDouble = dq.toDouble();
|
||||
BigDecimal actualBigDecimal = dq.toBigDecimal();
|
||||
String actualPlainString = dq.toPlainString();
|
||||
int actualSuppressedExponent = dq.getExponent();
|
||||
int actualSuppressedScientificExponent = dq.getExponent();
|
||||
int actualSuppressedCompactExponent = dq.getExponent();
|
||||
|
||||
assertEquals(
|
||||
String.format("formatted number %s toString: %f", skeleton, input),
|
||||
expectedString,
|
||||
actualString);
|
||||
assertEquals(
|
||||
String.format("compact decimal %s toLong: %f", skeleton, input),
|
||||
String.format("formatted number %s toLong: %f", skeleton, input),
|
||||
expectedLong,
|
||||
actualLong);
|
||||
assertDoubleEquals(
|
||||
String.format("compact decimal %s toDouble: %f", skeleton, input),
|
||||
String.format("formatted number %s toDouble: %f", skeleton, input),
|
||||
expectedDouble,
|
||||
actualDouble);
|
||||
assertBigDecimalEquals(
|
||||
String.format("compact decimal %s toBigDecimal: %f", skeleton, input),
|
||||
String.format("formatted number %s toBigDecimal: %f", skeleton, input),
|
||||
expectedBigDecimal,
|
||||
actualBigDecimal);
|
||||
assertEquals(
|
||||
|
@ -706,35 +710,45 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
expectedPlainString,
|
||||
actualPlainString);
|
||||
assertEquals(
|
||||
String.format("compact decimal %s suppressed exponent: %f", skeleton, input),
|
||||
expectedSuppressedExponent,
|
||||
actualSuppressedExponent);
|
||||
String.format("formatted number %s suppressed scientific exponent: %f", skeleton, input),
|
||||
expectedSuppressedScientificExponent,
|
||||
actualSuppressedScientificExponent);
|
||||
assertEquals(
|
||||
String.format("formatted number %s suppressed compact exponent: %f", skeleton, input),
|
||||
expectedSuppressedCompactExponent,
|
||||
actualSuppressedCompactExponent);
|
||||
|
||||
// test the actual computed values of the plural operands
|
||||
|
||||
double expectedNOperand = expectedDouble;
|
||||
double expectedIOperand = expectedLong;
|
||||
double expectedEOperand = expectedSuppressedExponent;
|
||||
double expectedEOperand = expectedSuppressedScientificExponent;
|
||||
double expectedCOperand = expectedSuppressedCompactExponent;
|
||||
double actualNOperand = dq.getPluralOperand(Operand.n);
|
||||
double actualIOperand = dq.getPluralOperand(Operand.i);
|
||||
double actualEOperand = dq.getPluralOperand(Operand.e);
|
||||
double actualCOperand = dq.getPluralOperand(Operand.c);
|
||||
|
||||
assertEquals(
|
||||
String.format("formatted number %s toString: %s", skeleton, input),
|
||||
expectedString,
|
||||
actualString);
|
||||
assertDoubleEquals(
|
||||
String.format("compact decimal %s n operand: %f", skeleton, input),
|
||||
String.format("formatted number %s n operand: %f", skeleton, input),
|
||||
expectedNOperand,
|
||||
actualNOperand);
|
||||
assertDoubleEquals(
|
||||
String.format("compact decimal %s i operand: %f", skeleton, input),
|
||||
String.format("formatted number %s i operand: %f", skeleton, input),
|
||||
expectedIOperand,
|
||||
actualIOperand);
|
||||
assertDoubleEquals(
|
||||
String.format("compact decimal %s e operand: %f", skeleton, input),
|
||||
String.format("formatted number %s e operand: %f", skeleton, input),
|
||||
expectedEOperand,
|
||||
actualEOperand);
|
||||
assertDoubleEquals(
|
||||
String.format("formatted number %s c operand: %f", skeleton, input),
|
||||
expectedCOperand,
|
||||
actualCOperand);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -760,6 +774,7 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
double expectedVOperand = 2;
|
||||
double expectedWOperand = 1;
|
||||
double expectedEOperand = 3;
|
||||
double expectedCOperand = 3;
|
||||
String expectedString = "1,23450 millier";
|
||||
double actualNOperand = dq.getPluralOperand(Operand.n);
|
||||
double actualIOperand = dq.getPluralOperand(Operand.i);
|
||||
|
@ -768,6 +783,7 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
double actualVOperand = dq.getPluralOperand(Operand.v);
|
||||
double actualWOperand = dq.getPluralOperand(Operand.w);
|
||||
double actualEOperand = dq.getPluralOperand(Operand.e);
|
||||
double actualCOperand = dq.getPluralOperand(Operand.c);
|
||||
String actualString = fn.toString();
|
||||
|
||||
assertDoubleEquals(
|
||||
|
@ -798,6 +814,10 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
String.format("compact decimal fraction e operand: %f", inputVal),
|
||||
expectedEOperand,
|
||||
actualEOperand);
|
||||
assertDoubleEquals(
|
||||
String.format("compact decimal fraction c operand: %f", inputVal),
|
||||
expectedCOperand,
|
||||
actualCOperand);
|
||||
assertEquals(
|
||||
String.format("compact decimal fraction toString: %f", inputVal),
|
||||
expectedString,
|
||||
|
@ -815,11 +835,12 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
|
||||
Object[][] casesData = {
|
||||
// input, compact long string output,
|
||||
// compact n operand, compact i operand, compact e operand
|
||||
{123456789, "123 millions", 123000000.0, 123000000.0, 6.0},
|
||||
{1234567, "1,2 million", 1200000.0, 1200000.0, 6.0},
|
||||
{123456, "123 mille", 123000.0, 123000.0, 3.0},
|
||||
{123, "123", 123.0, 123.0, 0.0},
|
||||
// compact n operand, compact i operand, compact e operand,
|
||||
// compact c operand
|
||||
{123456789, "123 millions", 123000000.0, 123000000.0, 6.0, 6.0},
|
||||
{1234567, "1,2 million", 1200000.0, 1200000.0, 6.0, 6.0},
|
||||
{123456, "123 mille", 123000.0, 123000.0, 3.0, 3.0},
|
||||
{123, "123", 123.0, 123.0, 0.0, 0.0},
|
||||
};
|
||||
|
||||
for (Object[] caseDatum : casesData) {
|
||||
|
@ -828,11 +849,12 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
double expectedNOperand = (double) caseDatum[2];
|
||||
double expectedIOperand = (double) caseDatum[3];
|
||||
double expectedEOperand = (double) caseDatum[4];
|
||||
double expectedCOperand = (double) caseDatum[5];
|
||||
|
||||
FormattedNumber fnCompactScaled = compactScaled.format(input);
|
||||
DecimalQuantity_DualStorageBCD dqCompactScaled =
|
||||
(DecimalQuantity_DualStorageBCD) fnCompactScaled.getFixedDecimal();
|
||||
double compactScaledEOperand = dqCompactScaled.getPluralOperand(Operand.e);
|
||||
double compactScaledCOperand = dqCompactScaled.getPluralOperand(Operand.c);
|
||||
|
||||
FormattedNumber fnCompact = compactLong.format(input);
|
||||
DecimalQuantity_DualStorageBCD dqCompact =
|
||||
|
@ -841,6 +863,7 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
double compactNOperand = dqCompact.getPluralOperand(Operand.n);
|
||||
double compactIOperand = dqCompact.getPluralOperand(Operand.i);
|
||||
double compactEOperand = dqCompact.getPluralOperand(Operand.e);
|
||||
double compactCOperand = dqCompact.getPluralOperand(Operand.c);
|
||||
assertEquals(
|
||||
String.format("formatted number compactLong toString: %s", input),
|
||||
expectedString,
|
||||
|
@ -857,14 +880,18 @@ public class DecimalQuantityTest extends TestFmwk {
|
|||
String.format("compact decimal %d, e operand vs. expected", input),
|
||||
expectedEOperand,
|
||||
compactEOperand);
|
||||
assertDoubleEquals(
|
||||
String.format("compact decimal %d, c operand vs. expected", input),
|
||||
expectedCOperand,
|
||||
compactCOperand);
|
||||
|
||||
// By scaling by 10^3 in a locale that has words / compact notation
|
||||
// based on powers of 10^3, we guarantee that the suppressed
|
||||
// exponent will differ by 3.
|
||||
assertDoubleEquals(
|
||||
String.format("decimal %d, e operand for compact vs. compact scaled", input),
|
||||
compactEOperand + 3,
|
||||
compactScaledEOperand);
|
||||
String.format("decimal %d, c operand for compact vs. compact scaled", input),
|
||||
compactCOperand + 3,
|
||||
compactScaledCOperand);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue