diff --git a/common/main/en.xml b/common/main/en.xml
index 771ee697ba2..97596cec099 100644
--- a/common/main/en.xml
+++ b/common/main/en.xml
@@ -6886,6 +6886,11 @@ annotations.
{0} part per million
{0} parts per million
+
+ parts per billion
+ {0} part per billion
+ {0} parts per billion
+
percent
{0} percent
@@ -7965,6 +7970,11 @@ annotations.
{0} ppm
{0} ppm
+
+ parts/billion
+ {0} ppb
+ {0} ppb
+
percent
{0}%
@@ -9041,6 +9051,11 @@ annotations.
{0}ppm
{0}ppm
+
+ ppb
+ {0}ppb
+ {0}ppb
+
%
{0}%
diff --git a/common/main/root.xml b/common/main/root.xml
index 4ccb65620f0..7b48cfdb9aa 100644
--- a/common/main/root.xml
+++ b/common/main/root.xml
@@ -5101,6 +5101,10 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/
ppm
{0} ppm
+
+ ppb
+ {0} ppb
+
%
{0}%
diff --git a/common/validity/unit.xml b/common/validity/unit.xml
index 65cba0bd2cb..2b07aa44b75 100644
--- a/common/validity/unit.xml
+++ b/common/validity/unit.xml
@@ -239,6 +239,7 @@ For terms of use, see http://www.unicode.org/copyright.html
volume-sai
volume-to-jp
volume-koku
+ concentr-portion-per-1e9
mass-fun
duration-night
diff --git a/tools/cldr-code/src/main/java/org/unicode/cldr/util/DtdData.java b/tools/cldr-code/src/main/java/org/unicode/cldr/util/DtdData.java
index 00a52df742b..e98963b2c36 100644
--- a/tools/cldr-code/src/main/java/org/unicode/cldr/util/DtdData.java
+++ b/tools/cldr-code/src/main/java/org/unicode/cldr/util/DtdData.java
@@ -1870,6 +1870,7 @@ private static final class UnitOrderHolder {
"volume-to-jp",
"volume-koku",
"mass-fun",
+ "concentr-portion-per-1e9",
"duration-night"))
.freeze();
}
diff --git a/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java b/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java
index 9da77ae9364..44620cfbb13 100644
--- a/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java
+++ b/tools/cldr-code/src/main/java/org/unicode/cldr/util/UnitConverter.java
@@ -1073,6 +1073,7 @@ public int compare(String o1, String o2) {
}
Comparator UNIT_COMPARATOR = new UnitComparator();
+ static final Pattern TRAILING_ZEROS = Pattern.compile("0+$");
/** Only handles the canonical units; no kilo-, only normalized, etc. */
// Thus we do not need to handle specials here
@@ -1174,7 +1175,7 @@ public String toString() {
for (int i = 1; i >= 0; --i) { // two passes, numerator then den.
boolean positivePass = i > 0;
if (positivePass && !factor.numerator.equals(BigInteger.ONE)) {
- builder.append(factor.numerator);
+ builder.append(shortConstant(factor.numerator));
}
Map target = positivePass ? numUnitsToPowers : denUnitsToPowers;
@@ -1190,7 +1191,7 @@ public String toString() {
firstDenominator = false;
builder.append("per-");
if (!factor.denominator.equals(BigInteger.ONE)) {
- builder.append(factor.denominator).append('-');
+ builder.append(shortConstant(factor.denominator)).append('-');
}
}
}
@@ -1213,10 +1214,35 @@ public String toString() {
}
builder.append(unit);
}
+ if (!positivePass
+ && firstDenominator
+ && !factor.denominator.equals(BigInteger.ONE)) {
+ builder.append("-per-").append(shortConstant(factor.denominator));
+ }
}
return builder.toString();
}
+ /**
+ * Return a string format. If larger than 7 digits, use 1eN format.
+ *
+ * @param source
+ * @return
+ */
+ public String shortConstant(BigInteger source) {
+ // don't bother optimizing
+ String result = source.toString();
+ if (result.length() < 8) {
+ return result;
+ }
+ Matcher matcher = TRAILING_ZEROS.matcher(result);
+ if (matcher.find()) {
+ int zeroCount = matcher.group().length();
+ return result.substring(0, result.length() - zeroCount) + "e" + zeroCount;
+ }
+ return result;
+ }
+
public String toString(
LocaleStringProvider resolvedFile,
String width,
diff --git a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestUnits.java b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestUnits.java
index dc0931a07b3..cedbe5e3dd4 100644
--- a/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestUnits.java
+++ b/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestUnits.java
@@ -3197,6 +3197,10 @@ public void TestUnitOrder() {
checkNormalization("test case", "newton-meter");
checkNormalization("test case", "acre-foot");
+ checkNormalization("test case", "portion-per-1e9");
+ checkNormalization("test case", "portion-per-1000");
+ checkNormalization("test case", "1e9-meter");
+ checkNormalization("test case", "1000-meter");
String stdAcre = converter.getStandardUnit("acre");