ICU-22781 Add support for converting units with constant denominators (C++)

See #3347
diff --git a/icu4c/source/i18n/units_converter.cpp b/icu4c/source/i18n/units_converter.cpp
index 3ccb006..1ab60bd 100644
--- a/icu4c/source/i18n/units_converter.cpp
+++ b/icu4c/source/i18n/units_converter.cpp
@@ -49,6 +49,8 @@ void U_I18N_API Factor::divideBy(const Factor &rhs) {
     offset = std::max(rhs.offset, offset);
 }
 
+void U_I18N_API Factor::divideBy(const uint64_t constant) { factorDen *= constant; }
+
 void U_I18N_API Factor::power(int32_t power) {
     // multiply all the constant by the power.
     for (int i = 0; i < CONSTANTS_COUNT; i++) {
@@ -239,6 +241,12 @@ Factor loadCompoundFactor(const MeasureUnitImpl &source, const ConversionRates &
         result.multiplyBy(singleFactor);
     }
 
+    // If the source has a constant denominator, then we need to divide the
+    // factor by the constant denominator.
+    if (source.constantDenominator != 0) {
+        result.divideBy(source.constantDenominator);
+    }
+
     return result;
 }
 
diff --git a/icu4c/source/i18n/units_converter.h b/icu4c/source/i18n/units_converter.h
index 01fa557..6f4b55f 100644
--- a/icu4c/source/i18n/units_converter.h
+++ b/icu4c/source/i18n/units_converter.h
@@ -82,6 +82,7 @@ struct U_I18N_API Factor {
 
     void multiplyBy(const Factor &rhs);
     void divideBy(const Factor &rhs);
+    void divideBy(const uint64_t constant);
 
     // Apply the power to the factor.
     void power(int32_t power);
diff --git a/icu4c/source/test/intltest/units_test.cpp b/icu4c/source/test/intltest/units_test.cpp
index 147d19c..0c342ea 100644
--- a/icu4c/source/test/intltest/units_test.cpp
+++ b/icu4c/source/test/intltest/units_test.cpp
@@ -361,6 +361,24 @@ void UnitsTest::testConverter() {
         {"dot-per-inch", "pixel-per-inch", 1.0, 1.0},
         {"dot", "pixel", 1.0, 1.0},
 
+        // Test with constants
+        {"meter-per-10", "foot", 1.0, 0.328084},
+        {"meter", "foot-per-10", 1.0, 32.8084},
+        {"meter", "foot-per-100", 1.0, 328.084},
+        {"portion", "portion-per-1000", 1.0, 1000},
+        {"portion", "portion-per-10000", 1.0, 10000},
+        {"portion", "portion-per-100000", 1.0, 100000},
+        {"portion", "portion-per-1000000", 1.0, 1000000},
+        {"portion-per-10", "portion", 1.0, 0.1},
+        {"portion-per-100", "portion", 1.0, 0.01},
+        {"portion-per-1000", "portion", 1.0, 0.001},
+        {"portion-per-10000", "portion", 1.0, 0.0001},
+        {"portion-per-100000", "portion", 1.0, 0.00001},
+        {"portion-per-1000000", "portion", 1.0, 0.000001},
+        {"mile-per-hour", "meter-per-second", 1.0, 0.44704},
+        {"mile-per-100-hour", "meter-per-100-second", 1.0, 0.44704},
+        {"mile-per-hour", "meter-per-100-second", 1.0, 44.704},
+        {"mile-per-100-hour", "meter-per-second", 1.0, 0.0044704},
     };
 
     for (const auto &testCase : testCases) {