ICU-21519 Add PluralOperand 'c' as alias to 'e', parse FixedDecimal strings
diff --git a/icu4c/source/i18n/number_decimalquantity.cpp b/icu4c/source/i18n/number_decimalquantity.cpp
index 74547c1..7720955 100644
--- a/icu4c/source/i18n/number_decimalquantity.cpp
+++ b/icu4c/source/i18n/number_decimalquantity.cpp
@@ -273,6 +273,9 @@
             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());
     }
diff --git a/icu4c/source/i18n/plurrule.cpp b/icu4c/source/i18n/plurrule.cpp
index e1e1667..bfcb6fb 100644
--- a/icu4c/source/i18n/plurrule.cpp
+++ b/icu4c/source/i18n/plurrule.cpp
@@ -60,6 +60,7 @@
 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 @@
                 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 @@
     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 @@
         case tVariableF:
         case tVariableT:
         case tVariableE:
+        case tVariableC:
         case tVariableV:
             U_ASSERT(curAndConstraint != nullptr);
             curAndConstraint->digitsType = type;
@@ -1092,6 +1094,8 @@
         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 @@
     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 @@
               type == tVariableF ||
               type == tVariableT ||
               type == tVariableE ||
+              type == tVariableC ||
               type == tVariableV ||
               type == tAt)) {
             status = U_UNEXPECTED_TOKEN;
@@ -1318,6 +1324,7 @@
              type != tVariableF &&
              type != tVariableT &&
              type != tVariableE &&
+             type != tVariableC &&
              type != tVariableV) {
             status = U_UNEXPECTED_TOKEN;
         }
@@ -1497,6 +1504,8 @@
         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 @@
         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(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 @@
     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 @@
         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 @@
 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);
 }
diff --git a/icu4c/source/i18n/plurrule_impl.h b/icu4c/source/i18n/plurrule_impl.h
index 52af3a7..ccc4813 100644
--- a/icu4c/source/i18n/plurrule_impl.h
+++ b/icu4c/source/i18n/plurrule_impl.h
@@ -145,6 +145,7 @@
   tVariableV,
   tVariableT,
   tVariableE,
+  tVariableC,
   tDecimal,
   tInteger,
   tEOF
@@ -222,12 +223,21 @@
     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.
      *
      * <p>Returns the integer value, but will fail if the number has fraction digits.
@@ -280,8 +290,10 @@
       * @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 @@
 
     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);
diff --git a/icu4c/source/test/intltest/numbertest.h b/icu4c/source/test/intltest/numbertest.h
index 3285ff7..39e8885 100644
--- a/icu4c/source/test/intltest/numbertest.h
+++ b/icu4c/source/test/intltest/numbertest.h
@@ -201,7 +201,7 @@
     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);
diff --git a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
index 74b97a9..610df96 100644
--- a/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
+++ b/icu4c/source/test/intltest/numbertest_decimalquantity.cpp
@@ -30,7 +30,7 @@
         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 @@
     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 @@
         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 @@
         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 @@
                 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 @@
         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 @@
         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 @@
                 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);
     }
 }
 
diff --git a/icu4c/source/test/intltest/plurults.cpp b/icu4c/source/test/intltest/plurults.cpp
index 9610fb6..407e484 100644
--- a/icu4c/source/test/intltest/plurults.cpp
+++ b/icu4c/source/test/intltest/plurults.cpp
@@ -52,8 +52,10 @@
     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 @@
     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 @@
     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 @@
     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 @@
     }
 }
 
+// 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));
 
diff --git a/icu4c/source/test/intltest/plurults.h b/icu4c/source/test/intltest/plurults.h
index 8e220dc..927a24d 100644
--- a/icu4c/source/test/intltest/plurults.h
+++ b/icu4c/source/test/intltest/plurults.h
@@ -32,9 +32,11 @@
     void testGetSamples();
     void testGetFixedDecimalSamples();
     void testSamplesWithExponent();
+    void testSamplesWithCompactNotation();
     void testWithin();
     void testGetAllKeywordValues();
     void testCompactDecimalPluralKeyword();
+    void testScientificPluralKeyword();
     void testOrdinal();
     void testSelect();
     void testSelectRange();
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 bce3400..2d98cc2 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
@@ -265,6 +265,9 @@
             return fractionCountWithoutTrailingZeros();
         case e:
             return getExponent();
+        case c:
+            // Plural operand `c` is currently an alias for `e`.
+            return getExponent();
         default:
             return Math.abs(toDouble());
         }
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 b302b4e..870b947 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
@@ -481,8 +481,8 @@
         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.
@@ -491,6 +491,19 @@
         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.
          *
          * <p>Returns the integer value, but will fail if the number has fraction digits.
@@ -657,10 +670,11 @@
          * @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 @@
             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.
             //
@@ -704,6 +722,15 @@
          * @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.
+         */
+        @Deprecated
         public FixedDecimal(double n, int v, long f) {
             this(n, v, f, 0);
         }
@@ -848,8 +875,11 @@
          */
         @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 @@
             case v: return visibleDecimalDigitCount;
             case w: return visibleDecimalDigitCountWithoutTrailingZeros;
             case e: return exponent;
+            case c: return exponent;
             default: return source;
             }
         }
@@ -970,10 +1001,10 @@
         @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;
             }
         }
 
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRulesTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRulesTest.java
index bca6fc9..b08f452 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRulesTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRulesTest.java
@@ -219,6 +219,37 @@
                 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 @@
         }
         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 @@
         }
     }
 
+    // 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 = {
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 9131382..ec2d598 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
@@ -609,55 +609,57 @@
     }
 
     @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 @@
             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 @@
             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 @@
                     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 @@
         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 @@
         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 @@
                 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 @@
 
         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 @@
             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 @@
             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 @@
                     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);
         }
     }