ICU-20164 Make NoUnit a zero-cost abstraction over MeasureUnit.

See #1230
diff --git a/icu4c/source/i18n/i18n.vcxproj b/icu4c/source/i18n/i18n.vcxproj
index 88083d2..e84cfbd 100644
--- a/icu4c/source/i18n/i18n.vcxproj
+++ b/icu4c/source/i18n/i18n.vcxproj
@@ -193,7 +193,6 @@
     <ClCompile Include="nfrs.cpp" />
     <ClCompile Include="nfrule.cpp" />
     <ClCompile Include="nfsubs.cpp" />
-    <ClCompile Include="nounit.cpp" />
     <ClCompile Include="number_affixutils.cpp" />
     <ClCompile Include="number_asformat.cpp" />
     <ClCompile Include="number_compact.cpp" />
diff --git a/icu4c/source/i18n/i18n.vcxproj.filters b/icu4c/source/i18n/i18n.vcxproj.filters
index 9565f43..a4ad63a 100644
--- a/icu4c/source/i18n/i18n.vcxproj.filters
+++ b/icu4c/source/i18n/i18n.vcxproj.filters
@@ -531,9 +531,6 @@
     <ClCompile Include="uregion.cpp">
       <Filter>formatting</Filter>
     </ClCompile>
-    <ClCompile Include="nounit.cpp">
-      <Filter>misc</Filter>
-    </ClCompile>
     <ClCompile Include="number_affixutils.cpp">
       <Filter>formatting</Filter>
     </ClCompile>
diff --git a/icu4c/source/i18n/i18n_uwp.vcxproj b/icu4c/source/i18n/i18n_uwp.vcxproj
index 3c6734b..327e498 100644
--- a/icu4c/source/i18n/i18n_uwp.vcxproj
+++ b/icu4c/source/i18n/i18n_uwp.vcxproj
@@ -414,7 +414,6 @@
     <ClCompile Include="nfrs.cpp" />
     <ClCompile Include="nfrule.cpp" />
     <ClCompile Include="nfsubs.cpp" />
-    <ClCompile Include="nounit.cpp" />
     <ClCompile Include="number_affixutils.cpp" />
     <ClCompile Include="number_asformat.cpp" />
     <ClCompile Include="number_compact.cpp" />
diff --git a/icu4c/source/i18n/measunit.cpp b/icu4c/source/i18n/measunit.cpp
index 8614f91..743032b 100644
--- a/icu4c/source/i18n/measunit.cpp
+++ b/icu4c/source/i18n/measunit.cpp
@@ -2266,15 +2266,6 @@
     fSubTypeId = result - gOffsets[fTypeId];
 }
 
-void MeasureUnit::initNoUnit(const char *subtype) {
-    int32_t result = binarySearch(gTypes, 0, UPRV_LENGTHOF(gTypes), "none");
-    U_ASSERT(result != -1);
-    fTypeId = result;
-    result = binarySearch(gSubTypes, gOffsets[fTypeId], gOffsets[fTypeId + 1], subtype);
-    U_ASSERT(result != -1);
-    fSubTypeId = result - gOffsets[fTypeId];
-}
-
 void MeasureUnit::setTo(int32_t typeId, int32_t subTypeId) {
     fTypeId = typeId;
     fSubTypeId = subTypeId;
diff --git a/icu4c/source/i18n/nounit.cpp b/icu4c/source/i18n/nounit.cpp
deleted file mode 100644
index 1d4aa05..0000000
--- a/icu4c/source/i18n/nounit.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// © 2017 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-
-#include "unicode/nounit.h"
-#include "uassert.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-U_NAMESPACE_BEGIN
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NoUnit)
-
-NoUnit U_EXPORT2 NoUnit::base() {
-    return NoUnit("");
-}
-
-NoUnit U_EXPORT2 NoUnit::percent() {
-    return NoUnit("percent");
-}
-
-NoUnit U_EXPORT2 NoUnit::permille() {
-    return NoUnit("permille");
-}
-
-NoUnit::NoUnit(const char* subtype) {
-    initNoUnit(subtype);
-}
-
-NoUnit::NoUnit(const NoUnit& other) : MeasureUnit(other) {
-}
-
-NoUnit* NoUnit::clone() const {
-    return new NoUnit(*this);
-}
-
-NoUnit::~NoUnit() {
-}
-
-
-U_NAMESPACE_END
-
-#endif
diff --git a/icu4c/source/i18n/number_formatimpl.cpp b/icu4c/source/i18n/number_formatimpl.cpp
index d5c3e6e..e6b1c5b 100644
--- a/icu4c/source/i18n/number_formatimpl.cpp
+++ b/icu4c/source/i18n/number_formatimpl.cpp
@@ -130,7 +130,7 @@
 
     // Pre-compute a few values for efficiency.
     bool isCurrency = utils::unitIsCurrency(macros.unit);
-    bool isNoUnit = utils::unitIsNoUnit(macros.unit);
+    bool isBaseUnit = utils::unitIsBaseUnit(macros.unit);
     bool isPercent = utils::unitIsPercent(macros.unit);
     bool isPermille = utils::unitIsPermille(macros.unit);
     bool isAccounting =
@@ -144,7 +144,7 @@
     if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) {
         unitWidth = macros.unitWidth;
     }
-    bool isCldrUnit = !isCurrency && !isNoUnit &&
+    bool isCldrUnit = !isCurrency && !isBaseUnit &&
         (unitWidth == UNUM_UNIT_WIDTH_FULL_NAME || !(isPercent || isPermille));
 
     // Select the numbering system.
diff --git a/icu4c/source/i18n/number_skeletons.cpp b/icu4c/source/i18n/number_skeletons.cpp
index 66cae73..58f7e2c 100644
--- a/icu4c/source/i18n/number_skeletons.cpp
+++ b/icu4c/source/i18n/number_skeletons.cpp
@@ -189,14 +189,11 @@
 MeasureUnit stem_to_object::unit(skeleton::StemEnum stem) {
     switch (stem) {
         case STEM_BASE_UNIT:
-            // Slicing is okay
-            return NoUnit::base(); // NOLINT
+            return MeasureUnit();
         case STEM_PERCENT:
-            // Slicing is okay
-            return NoUnit::percent(); // NOLINT
+            return MeasureUnit::getPercent();
         case STEM_PERMILLE:
-            // Slicing is okay
-            return NoUnit::permille(); // NOLINT
+            return MeasureUnit::getPermille();
         default:
             UPRV_UNREACHABLE;
     }
@@ -1521,17 +1518,15 @@
         }
         blueprint_helpers::generateCurrencyOption(currency, sb, status);
         return true;
-    } else if (utils::unitIsNoUnit(macros.unit)) {
-        if (utils::unitIsPercent(macros.unit)) {
-            sb.append(u"percent", -1);
-            return true;
-        } else if (utils::unitIsPermille(macros.unit)) {
-            sb.append(u"permille", -1);
-            return true;
-        } else {
-            // Default value is not shown in normalized form
-            return false;
-        }
+    } else if (utils::unitIsBaseUnit(macros.unit)) {
+        // Default value is not shown in normalized form
+        return false;
+    } else if (utils::unitIsPercent(macros.unit)) {
+        sb.append(u"percent", -1);
+        return true;
+    } else if (utils::unitIsPermille(macros.unit)) {
+        sb.append(u"permille", -1);
+        return true;
     } else {
         sb.append(u"measure-unit/", -1);
         blueprint_helpers::generateMeasureUnitOption(macros.unit, sb, status);
@@ -1541,14 +1536,9 @@
 
 bool GeneratorHelpers::perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) {
     // Per-units are currently expected to be only MeasureUnits.
-    if (utils::unitIsNoUnit(macros.perUnit)) {
-        if (utils::unitIsPercent(macros.perUnit) || utils::unitIsPermille(macros.perUnit)) {
-            status = U_UNSUPPORTED_ERROR;
-            return false;
-        } else {
-            // Default value: ok to ignore
-            return false;
-        }
+    if (utils::unitIsBaseUnit(macros.perUnit)) {
+        // Default value: ok to ignore
+        return false;
     } else if (utils::unitIsCurrency(macros.perUnit)) {
         status = U_UNSUPPORTED_ERROR;
         return false;
diff --git a/icu4c/source/i18n/number_utils.h b/icu4c/source/i18n/number_utils.h
index 93195f0..bc369c9 100644
--- a/icu4c/source/i18n/number_utils.h
+++ b/icu4c/source/i18n/number_utils.h
@@ -49,8 +49,8 @@
     return uprv_strcmp("currency", unit.getType()) == 0;
 }
 
-inline bool unitIsNoUnit(const MeasureUnit& unit) {
-    return uprv_strcmp("none", unit.getType()) == 0;
+inline bool unitIsBaseUnit(const MeasureUnit& unit) {
+    return unit == MeasureUnit();
 }
 
 inline bool unitIsPercent(const MeasureUnit& unit) {
diff --git a/icu4c/source/i18n/sources.txt b/icu4c/source/i18n/sources.txt
index 335e5ee..faaa14e 100644
--- a/icu4c/source/i18n/sources.txt
+++ b/icu4c/source/i18n/sources.txt
@@ -97,7 +97,6 @@
 nfrule.cpp
 nfsubs.cpp
 nortrans.cpp
-nounit.cpp
 nultrans.cpp
 number_affixutils.cpp
 number_asformat.cpp
diff --git a/icu4c/source/i18n/unicode/measunit.h b/icu4c/source/i18n/unicode/measunit.h
index 310e4ed..0e7f895 100644
--- a/icu4c/source/i18n/unicode/measunit.h
+++ b/icu4c/source/i18n/unicode/measunit.h
@@ -3353,12 +3353,6 @@
      */
     void initCurrency(StringPiece isoCurrency);
 
-    /**
-     * For ICU use only.
-     * @internal
-     */
-    void initNoUnit(const char *subtype);
-
 #endif  /* U_HIDE_INTERNAL_API */
 
 private:
diff --git a/icu4c/source/i18n/unicode/nounit.h b/icu4c/source/i18n/unicode/nounit.h
index 61b5c16..cee45e3 100644
--- a/icu4c/source/i18n/unicode/nounit.h
+++ b/icu4c/source/i18n/unicode/nounit.h
@@ -29,80 +29,53 @@
 
 /**
  * Dimensionless unit for percent and permille.
+ * Prior to ICU 68, this namespace was a class with the same name.
  * @see NumberFormatter
- * @draft ICU 60
+ * @draft ICU 68
  */
-class U_I18N_API NoUnit: public MeasureUnit {
-public:
+namespace NoUnit {
     /**
      * Returns an instance for the base unit (dimensionless and no scaling).
      *
-     * @return               a NoUnit instance
-     * @draft ICU 60
+     * Prior to ICU 68, this function returned a NoUnit by value.
+     *
+     * Since ICU 68, this function returns the same value as the default MeasureUnit constructor.
+     *
+     * @return               a MeasureUnit instance
+     * @draft ICU 68
      */
-    static NoUnit U_EXPORT2 base();
+    static inline MeasureUnit U_EXPORT2 base() {
+        return MeasureUnit();
+    }
 
     /**
      * Returns an instance for percent, or 1/100 of a base unit.
      *
-     * @return               a NoUnit instance
-     * @draft ICU 60
+     * Prior to ICU 68, this function returned a NoUnit by value.
+     *
+     * Since ICU 68, this function returns the same value as MeasureUnit::getPercent().
+     *
+     * @return               a MeasureUnit instance
+     * @draft ICU 68
      */
-    static NoUnit U_EXPORT2 percent();
+    static inline MeasureUnit U_EXPORT2 percent() {
+        return MeasureUnit::getPercent();
+    }
 
     /**
      * Returns an instance for permille, or 1/1000 of a base unit.
      *
-     * @return               a NoUnit instance
-     * @draft ICU 60
+     * Prior to ICU 68, this function returned a NoUnit by value.
+     *
+     * Since ICU 68, this function returns the same value as MeasureUnit::getPermille().
+     *
+     * @return               a MeasureUnit instance
+     * @draft ICU 68
      */
-    static NoUnit U_EXPORT2 permille();
-
-    /**
-     * Copy operator.
-     * @draft ICU 60
-     */
-    NoUnit(const NoUnit& other);
-
-    /**
-     * Destructor.
-     * @draft ICU 60
-     */
-    virtual ~NoUnit();
-
-    /**
-     * Return a polymorphic clone of this object.  The result will
-     * have the same class as returned by getDynamicClassID().
-     * @draft ICU 60
-     */
-    virtual NoUnit* clone() const;
-
-    /**
-     * Returns a unique class ID for this object POLYMORPHICALLY.
-     * This method implements a simple form of RTTI used by ICU.
-     * @return The class ID for this object. All objects of a given
-     * class have the same class ID.  Objects of other classes have
-     * different class IDs.
-     * @draft ICU 60
-     */
-    virtual UClassID getDynamicClassID() const;
-
-    /**
-     * Returns the class ID for this class. This is used to compare to
-     * the return value of getDynamicClassID().
-     * @return The class ID for all objects of this class.
-     * @draft ICU 60
-     */
-    static UClassID U_EXPORT2 getStaticClassID();
-
-private:
-    /**
-     * Constructor
-     * @internal (private)
-     */
-    NoUnit(const char* subtype);
-
-};
+    static inline MeasureUnit U_EXPORT2 permille() {
+        return MeasureUnit::getPermille();
+    }
+}
 
 U_NAMESPACE_END
 
diff --git a/icu4c/source/i18n/unicode/numberformatter.h b/icu4c/source/i18n/unicode/numberformatter.h
index 08f93cd..6ac33b4 100644
--- a/icu4c/source/i18n/unicode/numberformatter.h
+++ b/icu4c/source/i18n/unicode/numberformatter.h
@@ -1373,10 +1373,10 @@
     Notation notation;
 
     /** @internal */
-    MeasureUnit unit; // = NoUnit::base();
+    MeasureUnit unit;  // = MeasureUnit();  (the base dimensionless unit)
 
     /** @internal */
-    MeasureUnit perUnit; // = NoUnit::base();
+    MeasureUnit perUnit;  // = MeasureUnit();  (the base dimensionless unit)
 
     /** @internal */
     Precision precision;  // = Precision();  (bogus)
diff --git a/icu4c/source/test/depstest/dependencies.txt b/icu4c/source/test/depstest/dependencies.txt
index 9dfad52..82e2d44 100644
--- a/icu4c/source/test/depstest/dependencies.txt
+++ b/icu4c/source/test/depstest/dependencies.txt
@@ -1068,7 +1068,7 @@
     units bytestriebuilder bytestrie resourcebundle uclean_i18n
 
 group: units
-    measunit.o currunit.o nounit.o
+    measunit.o currunit.o
   deps
     stringenumeration errorcode
 
diff --git a/icu4c/source/test/intltest/numbertest_api.cpp b/icu4c/source/test/intltest/numbertest_api.cpp
index ad7a299..75b0d00 100644
--- a/icu4c/source/test/intltest/numbertest_api.cpp
+++ b/icu4c/source/test/intltest/numbertest_api.cpp
@@ -1013,6 +1013,18 @@
             Locale::getEnglish(),
             -98.7654321,
             u"-98.765432%");
+
+    assertFormatSingle(
+            u"Per Percent",
+            u"measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name",
+            u"measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name",
+            NumberFormatter::with()
+                    .unit(MeasureUnit::getMeter())
+                    .perUnit(MeasureUnit::getPercent())
+                    .unitWidth(UNUM_UNIT_WIDTH_FULL_NAME),
+            Locale::getEnglish(),
+            50,
+            u"50 meters per percent");
 }
 
 void NumberFormatterApiTest::percentParity() {
diff --git a/icu4c/source/test/intltest/uobjtest.cpp b/icu4c/source/test/intltest/uobjtest.cpp
index 3c4abb0..6b6a02c 100644
--- a/icu4c/source/test/intltest/uobjtest.cpp
+++ b/icu4c/source/test/intltest/uobjtest.cpp
@@ -276,7 +276,6 @@
 #include "unicode/msgfmt.h"
 #include "unicode/normlzr.h"
 #include "unicode/normalizer2.h"
-#include "unicode/nounit.h"
 #include "unicode/numfmt.h"
 #include "unicode/parsepos.h"
 #include "unicode/plurrule.h"
@@ -373,7 +372,6 @@
     TESTCLASSID_DEFAULT(Formattable);
 
     TESTCLASSID_FACTORY(MeasureUnit, MeasureUnit::createMeter(status));
-    TESTCLASSID_FACTORY(NoUnit, NoUnit::percent().clone());
     TESTCLASSID_FACTORY(TimeUnit, TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status));
     static const UChar SMALL_STR[] = u"QQQ";
     TESTCLASSID_CTOR(CurrencyAmount, (1.0, SMALL_STR, status));
diff --git a/icu4c/source/test/testdata/numberpermutationtest.txt b/icu4c/source/test/testdata/numberpermutationtest.txt
index 24136ad..e5f0b78 100644
--- a/icu4c/source/test/testdata/numberpermutationtest.txt
+++ b/icu4c/source/test/testdata/numberpermutationtest.txt
@@ -17,17 +17,17 @@
 
 compact-short percent unit-width-full-name
   es-MX
-    0 %
-    92 k
-    -0.22 %
+    0 por ciento
+    92 k por ciento
+    -0.22 por ciento
   zh-TW
     0%
-    9.2萬
+    9.2萬%
     -0.22%
   bn-BD
-    ০%
-    ৯২ হা
-    -০.২২%
+    ০শতাংশ
+    ৯২ হাশতাংশ
+    -০.২২শতাংশ
 
 compact-short currency/EUR unit-width-narrow
   es-MX
@@ -101,17 +101,17 @@
 
 scientific/+ee/sign-always percent unit-width-full-name
   es-MX
-    0E+00 %
-    9.182736E+04 %
-    -2.2222E-01 %
+    0E+00 por ciento
+    9.182736E+04 por ciento
+    -2.2222E-01 por ciento
   zh-TW
     0E+00%
     9.182736E+04%
     -2.2222E-01%
   bn-BD
-    ০E+০০%
-    ৯.১৮২৭৩৬E+০৪%
-    -২.২২২২E-০১%
+    ০E+০০শতাংশ
+    ৯.১৮২৭৩৬E+০৪শতাংশ
+    -২.২২২২E-০১শতাংশ
 
 scientific/+ee/sign-always currency/EUR unit-width-narrow
   es-MX
@@ -3139,59 +3139,59 @@
 
 percent unit-width-full-name precision-integer
   es-MX
-    0 %
-    91,827 %
-    -0 %
+    0 por ciento
+    91,827 por ciento
+    -0 por ciento
   zh-TW
     0%
     91,827%
     -0%
   bn-BD
-    ০%
-    ৯১,৮২৭%
-    -০%
+    ০শতাংশ
+    ৯১,৮২৭শতাংশ
+    -০শতাংশ
 
 percent unit-width-full-name .000
   es-MX
-    0.000 %
-    91,827.364 %
-    -0.222 %
+    0.000 por ciento
+    91,827.364 por ciento
+    -0.222 por ciento
   zh-TW
     0.000%
     91,827.364%
     -0.222%
   bn-BD
-    ০.০০০%
-    ৯১,৮২৭.৩৬৪%
-    -০.২২২%
+    ০.০০০শতাংশ
+    ৯১,৮২৭.৩৬৪শতাংশ
+    -০.২২২শতাংশ
 
 percent unit-width-full-name .##/@@@+
   es-MX
-    0 %
-    91,827.36 %
-    -0.222 %
+    0 por ciento
+    91,827.36 por ciento
+    -0.222 por ciento
   zh-TW
     0%
     91,827.36%
     -0.222%
   bn-BD
-    ০%
-    ৯১,৮২৭.৩৬%
-    -০.২২২%
+    ০শতাংশ
+    ৯১,৮২৭.৩৬শতাংশ
+    -০.২২২শতাংশ
 
 percent unit-width-full-name @@
   es-MX
-    0.0 %
-    92,000 %
-    -0.22 %
+    0.0 por ciento
+    92,000 por ciento
+    -0.22 por ciento
   zh-TW
     0.0%
     92,000%
     -0.22%
   bn-BD
-    ০.০%
-    ৯২,০০০%
-    -০.২২%
+    ০.০শতাংশ
+    ৯২,০০০শতাংশ
+    -০.২২শতাংশ
 
 currency/EUR unit-width-narrow precision-integer
   es-MX
@@ -3433,17 +3433,17 @@
 
 percent unit-width-full-name rounding-mode-floor
   es-MX
-    0 %
-    91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     91,827.3645%
     -0.22222%
   bn-BD
-    ০%
-    ৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০শতাংশ
+    ৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow rounding-mode-floor
   es-MX
@@ -3517,17 +3517,17 @@
 
 percent unit-width-full-name integer-width/##00
   es-MX
-    00 %
-    1827.3645 %
-    -00.22222 %
+    00 por ciento
+    1827.3645 por ciento
+    -00.22222 por ciento
   zh-TW
     00%
     1,827.3645%
     -00.22222%
   bn-BD
-    ০০%
-    ১,৮২৭.৩৬৪৫%
-    -০০.২২২২২%
+    ০০শতাংশ
+    ১,৮২৭.৩৬৪৫শতাংশ
+    -০০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow integer-width/##00
   es-MX
@@ -3601,17 +3601,17 @@
 
 percent unit-width-full-name scale/0.5
   es-MX
-    0 %
-    45,913.68225 %
-    -0.11111 %
+    0 por ciento
+    45,913.68225 por ciento
+    -0.11111 por ciento
   zh-TW
     0%
     45,913.68225%
     -0.11111%
   bn-BD
-    ০%
-    ৪৫,৯১৩.৬৮২২৫%
-    -০.১১১১১%
+    ০শতাংশ
+    ৪৫,৯১৩.৬৮২২৫শতাংশ
+    -০.১১১১১শতাংশ
 
 currency/EUR unit-width-narrow scale/0.5
   es-MX
@@ -3685,17 +3685,17 @@
 
 percent unit-width-full-name group-on-aligned
   es-MX
-    0 %
-    91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     91,827.3645%
     -0.22222%
   bn-BD
-    ০%
-    ৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০শতাংশ
+    ৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow group-on-aligned
   es-MX
@@ -3769,17 +3769,17 @@
 
 percent unit-width-full-name latin
   es-MX
-    0 %
-    91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     91,827.3645%
     -0.22222%
   bn-BD
-    0%
-    91,827.3645%
-    -0.22222%
+    0শতাংশ
+    91,827.3645শতাংশ
+    -0.22222শতাংশ
 
 currency/EUR unit-width-narrow latin
   es-MX
@@ -3853,17 +3853,17 @@
 
 percent unit-width-full-name sign-accounting-except-zero
   es-MX
-    0 %
-    +91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    +91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     +91,827.3645%
     -0.22222%
   bn-BD
-    ০%
-    +৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০শতাংশ
+    +৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow sign-accounting-except-zero
   es-MX
@@ -3937,17 +3937,17 @@
 
 percent unit-width-full-name decimal-always
   es-MX
-    0. %
-    91,827.3645 %
-    -0.22222 %
+    0. por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0.%
     91,827.3645%
     -0.22222%
   bn-BD
-    ০.%
-    ৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০.শতাংশ
+    ৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow decimal-always
   es-MX
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
index e0233f2..629732e 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberFormatterImpl.java
@@ -146,10 +146,8 @@
         return unit != null && "currency".equals(unit.getType());
     }
 
-    private static boolean unitIsNoUnit(MeasureUnit unit) {
-        // NOTE: In ICU4C, units cannot be null, and the default unit is a NoUnit.
-        // In ICU4J, return TRUE for a null unit from this method.
-        return unit == null || "none".equals(unit.getType());
+    private static boolean unitIsBaseUnit(MeasureUnit unit) {
+        return unit == null;
     }
 
     private static boolean unitIsPercent(MeasureUnit unit) {
@@ -181,7 +179,7 @@
 
         // Pre-compute a few values for efficiency.
         boolean isCurrency = unitIsCurrency(macros.unit);
-        boolean isNoUnit = unitIsNoUnit(macros.unit);
+        boolean isBaseUnit = unitIsBaseUnit(macros.unit);
         boolean isPercent = unitIsPercent(macros.unit);
         boolean isPermille = unitIsPermille(macros.unit);
         boolean isAccounting = macros.sign == SignDisplay.ACCOUNTING
@@ -192,7 +190,7 @@
         if (macros.unitWidth != null) {
             unitWidth = macros.unitWidth;
         }
-        boolean isCldrUnit = !isCurrency && !isNoUnit &&
+        boolean isCldrUnit = !isCurrency && !isBaseUnit &&
             (unitWidth == UnitWidth.FULL_NAME || !(isPercent || isPermille));
         PluralRules rules = macros.rules;
 
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java
index 33e60f7..e9ace79 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/number/NumberSkeletonImpl.java
@@ -1436,18 +1436,12 @@
                 sb.append("currency/");
                 BlueprintHelpers.generateCurrencyOption((Currency) macros.unit, sb);
                 return true;
-            } else if (macros.unit instanceof NoUnit) {
-                if (macros.unit == NoUnit.PERCENT) {
-                    sb.append("percent");
-                    return true;
-                } else if (macros.unit == NoUnit.PERMILLE) {
-                    sb.append("permille");
-                    return true;
-                } else {
-                    assert macros.unit == NoUnit.BASE;
-                    // Default value is not shown in normalized form
-                    return false;
-                }
+            } else if (macros.unit == MeasureUnit.PERCENT) {
+                sb.append("percent");
+                return true;
+            } else if (macros.unit == MeasureUnit.PERMILLE) {
+                sb.append("permille");
+                return true;
             } else {
                 sb.append("measure-unit/");
                 BlueprintHelpers.generateMeasureUnitOption(macros.unit, sb);
@@ -1457,7 +1451,7 @@
 
         private static boolean perUnit(MacroProps macros, StringBuilder sb) {
             // Per-units are currently expected to be only MeasureUnits.
-            if (macros.perUnit instanceof Currency || macros.perUnit instanceof NoUnit) {
+            if (macros.perUnit instanceof Currency) {
                 throw new UnsupportedOperationException(
                         "Cannot generate number skeleton with per-unit that is not a standard measure unit");
             } else {
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java b/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java
index 356ca99..20a7850 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/MeasureUnit.java
@@ -197,8 +197,6 @@
             factory = CURRENCY_FACTORY;
         } else if ("duration".equals(type)) {
             factory = TIMEUNIT_FACTORY;
-        } else if ("none".equals(type)) {
-            factory = NOUNIT_FACTORY;
         } else {
             factory = UNIT_FACTORY;
         }
@@ -294,13 +292,6 @@
         }
     };
 
-    static Factory NOUNIT_FACTORY = new Factory() {
-        @Override
-        public MeasureUnit create(String type, String subType) {
-           return new NoUnit(subType);
-        }
-    };
-
     /**
      * Sink for enumerating the available measure units.
      */
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java b/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java
index 7a0aba8..a767e62 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/util/NoUnit.java
@@ -7,47 +7,46 @@
 /**
  * Dimensionless unit for percent and permille.
  * @see NumberFormatter
- * @draft ICU 60
+ * @draft ICU 68
  * @provisional This API might change or be removed in a future release.
  */
-public class NoUnit extends MeasureUnit {
-    private static final long serialVersionUID = 2467174286237024095L;
-
+public final class NoUnit {
     /**
      * Constant for the base unit (dimensionless and no scaling).
      *
-     * @draft ICU 60
+     * Prior to ICU 68, this constant equaled an instance of NoUnit.
+     *
+     * Since ICU 68, this constant equals null.
+     *
+     * @draft ICU 68
      * @provisional This API might change or be removed in a future release.
      */
-    public static final NoUnit BASE =
-        (NoUnit) MeasureUnit.internalGetInstance("none", "base");
+    public static final MeasureUnit BASE = null;
 
     /**
      * Constant for the percent unit, or 1/100 of a base unit.
      *
-     * @draft ICU 60
+     * Prior to ICU 68, this constant equaled an instance of NoUnit.
+     *
+     * Since ICU 68, this constant is equivalent to MeasureUnit.PERCENT.
+     *
+     * @draft ICU 68
      * @provisional This API might change or be removed in a future release.
      */
-    public static final NoUnit PERCENT =
-        (NoUnit) MeasureUnit.internalGetInstance("none", "percent");
+    public static final MeasureUnit PERCENT = MeasureUnit.PERCENT;
 
     /**
      * Constant for the permille unit, or 1/100 of a base unit.
      *
-     * @draft ICU 60
+     * Prior to ICU 68, this constant equaled an instance of NoUnit.
+     *
+     * Since ICU 68, this constant is equivalent to MeasureUnit.PERMILLE.
+     *
+     * @draft ICU 68
      * @provisional This API might change or be removed in a future release.
      */
-    public static final NoUnit PERMILLE =
-        (NoUnit) MeasureUnit.internalGetInstance("none", "permille");
+    public static final MeasureUnit PERMILLE = MeasureUnit.PERMILLE;
 
-
-    /**
-     * Package local constructor. This class is not designed for subclassing
-     * by ICU users.
-     *
-     * @param subType   The unit subtype.
-     */
-    NoUnit(String subType) {
-        super("none", subType);
-    }
+    // This class is a namespace not intended to be instantiated:
+    private NoUnit() {}
 }
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
index 24136ad..e5f0b78 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/data/numberpermutationtest.txt
@@ -17,17 +17,17 @@
 
 compact-short percent unit-width-full-name
   es-MX
-    0 %
-    92 k
-    -0.22 %
+    0 por ciento
+    92 k por ciento
+    -0.22 por ciento
   zh-TW
     0%
-    9.2萬
+    9.2萬%
     -0.22%
   bn-BD
-    ০%
-    ৯২ হা
-    -০.২২%
+    ০শতাংশ
+    ৯২ হাশতাংশ
+    -০.২২শতাংশ
 
 compact-short currency/EUR unit-width-narrow
   es-MX
@@ -101,17 +101,17 @@
 
 scientific/+ee/sign-always percent unit-width-full-name
   es-MX
-    0E+00 %
-    9.182736E+04 %
-    -2.2222E-01 %
+    0E+00 por ciento
+    9.182736E+04 por ciento
+    -2.2222E-01 por ciento
   zh-TW
     0E+00%
     9.182736E+04%
     -2.2222E-01%
   bn-BD
-    ০E+০০%
-    ৯.১৮২৭৩৬E+০৪%
-    -২.২২২২E-০১%
+    ০E+০০শতাংশ
+    ৯.১৮২৭৩৬E+০৪শতাংশ
+    -২.২২২২E-০১শতাংশ
 
 scientific/+ee/sign-always currency/EUR unit-width-narrow
   es-MX
@@ -3139,59 +3139,59 @@
 
 percent unit-width-full-name precision-integer
   es-MX
-    0 %
-    91,827 %
-    -0 %
+    0 por ciento
+    91,827 por ciento
+    -0 por ciento
   zh-TW
     0%
     91,827%
     -0%
   bn-BD
-    ০%
-    ৯১,৮২৭%
-    -০%
+    ০শতাংশ
+    ৯১,৮২৭শতাংশ
+    -০শতাংশ
 
 percent unit-width-full-name .000
   es-MX
-    0.000 %
-    91,827.364 %
-    -0.222 %
+    0.000 por ciento
+    91,827.364 por ciento
+    -0.222 por ciento
   zh-TW
     0.000%
     91,827.364%
     -0.222%
   bn-BD
-    ০.০০০%
-    ৯১,৮২৭.৩৬৪%
-    -০.২২২%
+    ০.০০০শতাংশ
+    ৯১,৮২৭.৩৬৪শতাংশ
+    -০.২২২শতাংশ
 
 percent unit-width-full-name .##/@@@+
   es-MX
-    0 %
-    91,827.36 %
-    -0.222 %
+    0 por ciento
+    91,827.36 por ciento
+    -0.222 por ciento
   zh-TW
     0%
     91,827.36%
     -0.222%
   bn-BD
-    ০%
-    ৯১,৮২৭.৩৬%
-    -০.২২২%
+    ০শতাংশ
+    ৯১,৮২৭.৩৬শতাংশ
+    -০.২২২শতাংশ
 
 percent unit-width-full-name @@
   es-MX
-    0.0 %
-    92,000 %
-    -0.22 %
+    0.0 por ciento
+    92,000 por ciento
+    -0.22 por ciento
   zh-TW
     0.0%
     92,000%
     -0.22%
   bn-BD
-    ০.০%
-    ৯২,০০০%
-    -০.২২%
+    ০.০শতাংশ
+    ৯২,০০০শতাংশ
+    -০.২২শতাংশ
 
 currency/EUR unit-width-narrow precision-integer
   es-MX
@@ -3433,17 +3433,17 @@
 
 percent unit-width-full-name rounding-mode-floor
   es-MX
-    0 %
-    91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     91,827.3645%
     -0.22222%
   bn-BD
-    ০%
-    ৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০শতাংশ
+    ৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow rounding-mode-floor
   es-MX
@@ -3517,17 +3517,17 @@
 
 percent unit-width-full-name integer-width/##00
   es-MX
-    00 %
-    1827.3645 %
-    -00.22222 %
+    00 por ciento
+    1827.3645 por ciento
+    -00.22222 por ciento
   zh-TW
     00%
     1,827.3645%
     -00.22222%
   bn-BD
-    ০০%
-    ১,৮২৭.৩৬৪৫%
-    -০০.২২২২২%
+    ০০শতাংশ
+    ১,৮২৭.৩৬৪৫শতাংশ
+    -০০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow integer-width/##00
   es-MX
@@ -3601,17 +3601,17 @@
 
 percent unit-width-full-name scale/0.5
   es-MX
-    0 %
-    45,913.68225 %
-    -0.11111 %
+    0 por ciento
+    45,913.68225 por ciento
+    -0.11111 por ciento
   zh-TW
     0%
     45,913.68225%
     -0.11111%
   bn-BD
-    ০%
-    ৪৫,৯১৩.৬৮২২৫%
-    -০.১১১১১%
+    ০শতাংশ
+    ৪৫,৯১৩.৬৮২২৫শতাংশ
+    -০.১১১১১শতাংশ
 
 currency/EUR unit-width-narrow scale/0.5
   es-MX
@@ -3685,17 +3685,17 @@
 
 percent unit-width-full-name group-on-aligned
   es-MX
-    0 %
-    91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     91,827.3645%
     -0.22222%
   bn-BD
-    ০%
-    ৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০শতাংশ
+    ৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow group-on-aligned
   es-MX
@@ -3769,17 +3769,17 @@
 
 percent unit-width-full-name latin
   es-MX
-    0 %
-    91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     91,827.3645%
     -0.22222%
   bn-BD
-    0%
-    91,827.3645%
-    -0.22222%
+    0শতাংশ
+    91,827.3645শতাংশ
+    -0.22222শতাংশ
 
 currency/EUR unit-width-narrow latin
   es-MX
@@ -3853,17 +3853,17 @@
 
 percent unit-width-full-name sign-accounting-except-zero
   es-MX
-    0 %
-    +91,827.3645 %
-    -0.22222 %
+    0 por ciento
+    +91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0%
     +91,827.3645%
     -0.22222%
   bn-BD
-    ০%
-    +৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০শতাংশ
+    +৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow sign-accounting-except-zero
   es-MX
@@ -3937,17 +3937,17 @@
 
 percent unit-width-full-name decimal-always
   es-MX
-    0. %
-    91,827.3645 %
-    -0.22222 %
+    0. por ciento
+    91,827.3645 por ciento
+    -0.22222 por ciento
   zh-TW
     0.%
     91,827.3645%
     -0.22222%
   bn-BD
-    ০.%
-    ৯১,৮২৭.৩৬৪৫%
-    -০.২২২২২%
+    ০.শতাংশ
+    ৯১,৮২৭.৩৬৪৫শতাংশ
+    -০.২২২২২শতাংশ
 
 currency/EUR unit-width-narrow decimal-always
   es-MX
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
index 3056545..d3bbc13 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterApiTest.java
@@ -966,6 +966,19 @@
                 ULocale.ENGLISH,
                 -98.7654321,
                 "-98.765432%");
+
+        assertFormatSingle(
+                "Per Percent",
+                "measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name",
+                "measure-unit/length-meter per-measure-unit/concentr-percent unit-width-full-name",
+                NumberFormatter.with()
+                        .unit(MeasureUnit.METER)
+                        .perUnit(MeasureUnit.PERCENT)
+                        .unitWidth(UnitWidth.FULL_NAME),
+                ULocale.ENGLISH,
+                50,
+                "50 meters per percent");
+
     }
 
     @Test