diff --git a/.gitattributes b/.gitattributes index 963c32abfaa..45d173746ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -245,6 +245,7 @@ icu4j/main/classes/core/.project -text icu4j/main/classes/core/.settings/org.eclipse.core.resources.prefs -text icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text icu4j/main/classes/core/manifest.stub -text +icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java -text icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text icu4j/main/classes/currdata/.settings/org.eclipse.core.resources.prefs -text icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java new file mode 100644 index 00000000000..8a1e7f54a70 --- /dev/null +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalDataCache.java @@ -0,0 +1,165 @@ +/* + ******************************************************************************* + * Copyright (C) 2012, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.text; + +import com.ibm.icu.impl.ICUCache; +import com.ibm.icu.impl.ICUResourceBundle; +import com.ibm.icu.impl.SimpleCache; +import com.ibm.icu.util.ULocale; +import com.ibm.icu.util.UResourceBundle; + +/** + * A cache containing data by locale for {@link CompactDecimalFormat} + * + * @author Travis Keep + */ +class CompactDecimalDataCache { + + private static final int MAX_DIGITS = 15; + private final ICUCache cache = new SimpleCache(); + + /** + * Data contains the compact decimal data for a particular locale. Data consists + * of three arrays. The index of each array corresponds to log10 of the number + * being formatted, so when formatting 12,345, the 4th index of the arrays should + * be used. Divisors contain the number to divide by before doing formatting. + * In the case of english, divisors[4] is 1000. So to format + * 12,345, divide by 1000 to get 12. prefix and suffix contain the prefix and + * suffix to use, for english, suffix[4] is "K" So ultimately, + * 12,345 is formatted as 12K. + * + * Each array in data is 15 in length, and every index is filled. + * + * @author Travis Keep + * * + */ + static class Data { + long[] divisors; + String[] prefixes; + String[] suffixes; + + Data(long[] divisors, String[] prefixes, String[] suffixes) { + this.divisors = divisors; + this.prefixes = prefixes; + this.suffixes = suffixes; + } + } + + /** + * Fetch data for a particular locale. + */ + Data get(ULocale locale) { + Data result = cache.get(locale); + if (result == null) { + result = load(locale); + cache.put(locale, result); + } + return result; + } + + private static Data load(ULocale ulocale) { + NumberingSystem ns = NumberingSystem.getInstance(ulocale); + ICUResourceBundle r = (ICUResourceBundle)UResourceBundle. + getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, ulocale); + r = r.getWithFallback("NumberElements/" + ns.getName() + "/patternsShort/decimalFormat"); + int size = r.getSize(); + Data result = new Data( + new long[MAX_DIGITS], new String[MAX_DIGITS], new String[MAX_DIGITS]); + for (int i = 0; i < size; i++) { + populateData((ICUResourceBundle) r.get(i), result); + } + fillInMissingAndFixRedundant(result); + return result; + } + + /** + * Populates Data object with data for a particular divisor from resource bundle. + */ + private static void populateData(ICUResourceBundle divisorData, Data result) { + long divisor = Long.parseLong(divisorData.getKey()); + int thisIndex = (int) Math.log10(divisor); + // Silently ignore divisors that are too big. + if (thisIndex >= MAX_DIGITS) { + return; + } + ICUResourceBundle other = (ICUResourceBundle) divisorData.get("other"); + populatePrefixSuffix(other.getString(), thisIndex, result); + result.divisors[thisIndex] = divisor; + } + + /** + * Extracts the prefix and suffix from the template and places them in the + * Data object. + * @param template the number template, e.g 000K + * @param idx the index to store the extracted prefix and suffix + * @param result Data object modified in-place here. + */ + private static void populatePrefixSuffix(String template, int idx, Data result) { + int firstIdx = template.indexOf("0"); + int lastIdx = template.lastIndexOf("0"); + result.prefixes[idx] = template.substring(0, firstIdx); + result.suffixes[idx] = template.substring(lastIdx + 1); + } + + /** + * After reading information from resource bundle into a Data object, there + * is no guarantee that every index of the arrays will be filled. Moreover, + * the resource bundle may contain redundant information. After reading + * the resource for english, we may end up with: + *
+     * index divisor prefix suffix
+     * 0        
+     * 1        
+     * 2        
+     * 3     1000           K
+     * 4     10000          K
+     * 5     100000         K
+     * 6     1000000        M
+     * ...
+     * 
+ * The 10000 and 100000 are redundant. In fact, this data will cause CompactDecimalFormatter + * to format 12345 as 1.2K instead of 12K. Moreover, no data was populated for + * indexes 0, 1, or 2. What we want is something like this: + *
+     * index divisor prefix suffix
+     * 0     1
+     * 1     1
+     * 2     1
+     * 3     1000           K
+     * 4     1000           K
+     * 5     1000           K
+     * 6     1000000        M
+     * ...
+     * 
+ * This function walks through the arrays filling in missing data and replacing + * redundant data. If prefix is missing for an index, we fill in that index + * with the values from the previous index. If prefix and suffix for an index + * are the same as the previous index, we consider that redundant data and we + * replace the divisor with the one from the previous index. + * + * @param result this instance is fixed in-place. + */ + private static void fillInMissingAndFixRedundant(Data result) { + // Initially we assume that previous divisor is 1 with no prefix or suffix. + long lastDivisor = 1L; + String lastPrefix = ""; + String lastSuffix = ""; + for (int i = 0; i < result.divisors.length; i++) { + if (result.prefixes[i] == null) { + result.divisors[i] = lastDivisor; + result.prefixes[i] = lastPrefix; + result.suffixes[i] = lastSuffix; + } else if (result.prefixes[i].equals(lastPrefix) && result.suffixes[i].equals(lastSuffix)) { + result.divisors[i] = lastDivisor; + } else { + lastDivisor = result.divisors[i]; + lastPrefix = result.prefixes[i]; + lastSuffix = result.suffixes[i]; + } + } + } +} diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java index 1e25cd21da6..8f4be370288 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java @@ -39,7 +39,7 @@ import com.ibm.icu.util.ULocale; *

* Note that important methods, like setting the number of decimals, will be moved up from DecimalFormat to * NumberFormat. - * + * * @author markdavis * @draft ICU 49 * @provisional This API might change or be removed in a future release. @@ -49,6 +49,7 @@ public class CompactDecimalFormat extends DecimalFormat { private static final int MINIMUM_ARRAY_LENGTH = 15; private static final int POSITIVE_PREFIX = 0, POSITIVE_SUFFIX = 1, AFFIX_SIZE = 2; + private static final CompactDecimalDataCache cache = new CompactDecimalDataCache(); private final String[] prefix; private final String[] suffix; @@ -57,7 +58,7 @@ public class CompactDecimalFormat extends DecimalFormat { /** * The public mechanism is NumberFormat.getCompactDecimalInstance(). - * + * * @param locale * the desired locale * @param style @@ -65,17 +66,11 @@ public class CompactDecimalFormat extends DecimalFormat { */ CompactDecimalFormat(ULocale locale, CompactStyle style) { DecimalFormat format = (DecimalFormat) NumberFormat.getInstance(locale); - Data data; - while (true) { - data = localeToData.get(locale); - if (data != null) { - break; - } - locale = locale.equals(zhTW) ? ULocale.TRADITIONAL_CHINESE : locale.getFallback(); - } + CompactDecimalDataCache.Data data = cache.get(locale); this.prefix = data.prefixes; this.suffix = data.suffixes; this.divisor = data.divisors; + // TODO fix to consider plural form when choosing a prefix or suffix. applyPattern(format.toPattern()); setDecimalFormatSymbols(format.getDecimalFormatSymbols()); setMaximumSignificantDigits(2); // default significant digits @@ -94,7 +89,7 @@ public class CompactDecimalFormat extends DecimalFormat { * parallel, and provide the information for each power of 10. When formatting a value, the correct power of 10 is * found, then the value is divided by the divisor, and the prefix and suffix are set (using * setPositivePrefix/Suffix). - * + * * @param pattern * A number format pattern. Note that the prefix and suffix are discarded, and the decimals are * overridden by default. @@ -232,20 +227,20 @@ public class CompactDecimalFormat extends DecimalFormat { public Number parse(String text, ParsePosition parsePosition) { throw new UnsupportedOperationException(); } - + // DISALLOW Serialization, at least while draft - + private void writeObject(ObjectOutputStream out) throws IOException { throw new NotSerializableException(); } - + private void readObject(ObjectInputStream in) throws IOException { throw new NotSerializableException(); } /* INTERNALS */ - private static ULocale zhTW = new ULocale("zh_TW"); + private void recordError(Collection creationErrors, String errorMessage) { if (creationErrors == null) { @@ -253,29 +248,4 @@ public class CompactDecimalFormat extends DecimalFormat { } creationErrors.add(errorMessage); } - - /** JUST FOR DEVELOPMENT */ - // For use with the hard-coded data - static class Data { - public Data(long[] divisors, String[] prefixes, String[] suffixes) { - this.divisors = divisors; - this.prefixes = prefixes; - this.suffixes = suffixes; - } - - long[] divisors; - String[] prefixes; - String[] suffixes; - } - - static Map localeToData = new HashMap(); - - static void add(String locale, long[] ls, String[] prefixes, String[] suffixes) { - localeToData.put(new ULocale(locale), new Data(ls, prefixes, suffixes)); - } - - static { - CompactDecimalFormatData.load(); - } - } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormatData.java b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormatData.java deleted file mode 100644 index 495c107a83a..00000000000 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormatData.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - ******************************************************************************* - * Copyright (C) 1996-2012, Google, International Business Machines Corporation and - * others. All Rights Reserved. * - ******************************************************************************* - */ -package com.ibm.icu.text; - -/** - * Only until we access the data from CLDR. - */ -class CompactDecimalFormatData { - static void load() { - CompactDecimalFormat.add("af", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " mil", " mil", " mil", " mjd", " mjd", " mjd", " bil", " bil", " bil"}); - CompactDecimalFormat.add("am", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "ኪባ", " ሜትር", " ሜትር", " ሜትር", "G", "G", "G", "T", "T", "T"}); - CompactDecimalFormat.add("ar", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("bg", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " Х", " Х", " Х", " М", " М", " М", " Б", " Б", " Б", " Т", " Т", " Т"}); - CompactDecimalFormat.add("bn", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("ca", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " M", " M", " M", " M", "k M", "k M", " B", " B", " B"}); - CompactDecimalFormat.add("cs", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " tis.", " tis.", " tis.", " mil.", " mil.", " mil.", " mld.", " mld.", " mld.", " bil.", " bil.", " bil."}); - CompactDecimalFormat.add("da", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " mio", " mio", " mio", " mia", " mia", " mia", " bill", " bill", " bill"}); - CompactDecimalFormat.add("de", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " Mio", " Mio", " Mio", " Mrd", " Mrd", " Mrd", " B", " B", " B"}); - CompactDecimalFormat.add("el", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " χιλ.", " χιλ.", " χιλ.", " εκ.", " εκ.", " εκ.", " δις", " δις", " δις", " τρις", " τρις", " τρις"}); - CompactDecimalFormat.add("en", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("es", - new long[]{1L, 1L, 1L, 1L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "k", "k", " M", " M", " M", " M", "k M", "k M", " B", " B", " B"}); - CompactDecimalFormat.add("et", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " tuh", " tuh", " tuh", " mln", " mln", " mln", " mld", " mld", " mld", " trl", " trl", " trl"}); - CompactDecimalFormat.add("eu", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " M", " M", " M", " M", "k M", "k M", " B", " B", " B"}); - CompactDecimalFormat.add("fa", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("fi", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " t", " t", " t", " ml", " ml", " ml", " mr", " mr", " mr", " b", " b", " b"}); - CompactDecimalFormat.add("fil", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("fr", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " M", " M", " M", " Md", " Mds", " Mds", " Bn", " Bn", " Bn"}); - CompactDecimalFormat.add("gl", - new long[]{1L, 1L, 1L, 1L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "k", "k", " M", " M", " M", " M", "k M", "k M", " B", " B", " B"}); - CompactDecimalFormat.add("gu", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("he", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("hi", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("hr", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " mil.", " mil.", " mil.", " mlr", " mlr", " mlr", " bil.", " bil.", " bil."}); - CompactDecimalFormat.add("hu", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " e", " e", " e", " m", " m", " m", " mrd", " mrd", " mrd", " b", " b", " b"}); - CompactDecimalFormat.add("id", - new long[]{1L, 1L, 1L, 1L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", " rb", " rb", " jt", " jt", " jt", " M", " M", " M", " T", " T", " T"}); - CompactDecimalFormat.add("is", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " þ.", " þ.", " þ.", " m.", " m.", " m.", " ma.", " ma.", " ma.", " tr.", " tr.", " tr."}); - CompactDecimalFormat.add("it", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " M", " M", " M", " Md", " Md", " Md", " B", " B", " B"}); - CompactDecimalFormat.add("ja", - new long[]{1L, 1L, 1L, 1L, 10000L, 10000L, 10000L, 10000L, 100000000L, 100000000L, 100000000L, 100000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "万", "万", "万", "万", "億", "億", "億", "億", "兆", "兆", "兆"}); - CompactDecimalFormat.add("kn", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("ko", - new long[]{1L, 1L, 1L, 1L, 10000L, 10000L, 10000L, 10000L, 100000000L, 100000000L, 100000000L, 100000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "만", "만", "만", "만", "억", "억", "억", "억", "조", "조", "조"}); - CompactDecimalFormat.add("lt", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " K", " K", " K", " M", " M", " M", " G", " G", " G", " T", " T", " T"}); - CompactDecimalFormat.add("lv", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " K", " K", " K", " M", " M", " M", " G", " G", " G", " T", " T", " T"}); - CompactDecimalFormat.add("ml", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("mr", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("ms", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("nb", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " mill", " mill", " mill", " mrd", " mrd", " mrd", " bill", " bill", " bill"}); - CompactDecimalFormat.add("nl", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " mln", " mln", " mln", " mld", " mld", " mld", " bilj", " bilj", " bilj"}); - CompactDecimalFormat.add("pl", - new long[]{1L, 1L, 1L, 1L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", " tys.", " tys.", " mln", " mln", " mln", " mld", " mld", " mld", " bln", " bln", " bln"}); - CompactDecimalFormat.add("pt", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " mil", " mil", " mil", " mi", " mi", " mi", " bi", " bi", " bi", " tri", " tri", " tri"}); - CompactDecimalFormat.add("ro", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " mii", " mii", " mii", " mil.", " mil.", " mil.", " mld.", " mld.", " mld.", " bln.", " bln.", " bln."}); - CompactDecimalFormat.add("ru", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " тыс.", " тыс.", " тыс.", " млн", " млн", " млн", " млрд", " млрд", " млрд", " трлн", " трлн", " трлн"}); - CompactDecimalFormat.add("sk", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " tis.", " tis.", " tis.", " mil.", " mil.", " mil.", " mld.", " mld.", " mld.", " bil.", " bil.", " bil."}); - CompactDecimalFormat.add("sl", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " tis.", " tis.", " tis.", " mio.", " mio.", " mio.", " mrd.", " mrd.", " mrd.", " bil.", " bil.", " bil."}); - CompactDecimalFormat.add("sr", - new long[]{1L, 1L, 1L, 1L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", " хиљ", " хиљ", " мил", " мил", " мил", " млрд", " млрд", " млрд", " бил", " бил", " бил"}); - CompactDecimalFormat.add("sv", - new long[]{1L, 1L, 1L, 1L, 1L, 1L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "", "", " mjn", " mjn", " mjn", " mjd", " mjd", " mjd", " trl", " trl", " trl"}); - CompactDecimalFormat.add("sw", - new long[]{1L, 1L, 1L, 1000L, 1000L, 100000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "elfu ", "elfu ", "laki", "M", "M", "M", "B", "B", "B", "T", "T", "T"}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}); - CompactDecimalFormat.add("ta", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("te", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("th", - new long[]{1L, 1L, 1L, 1000L, 10000L, 100000L, 1000000L, 1000000L, 1000000L, 1000000000L, 10000000000L, 100000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " พัน", "หมื่น", "แสน", " ล้าน", " ล้าน", " ล.", " พ.ล.", " ม.ล.", " ส.ล.", " ล.ล.", " ล.ล", " ล.ล."}); - CompactDecimalFormat.add("tr", - new long[]{1L, 1L, 1L, 1L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", " B", " B", " Mn", " Mn", " Mn", " Mr", " Mr", " Mr", " T", " T", " T"}); - CompactDecimalFormat.add("uk", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " тис", " тис", " тис", " млн", " млн", " млн", " млрд", " млрд", " млрд", " трлн", " трлн", " трлн"}); - CompactDecimalFormat.add("ur", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "K", "K", "K", "M", "M", "M", "B", "B", "B", "T", "T", "T"}); - CompactDecimalFormat.add("vi", - new long[]{1L, 1L, 1L, 1000L, 1000L, 1000L, 1000000L, 1000000L, 1000000L, 1000000000L, 1000000000L, 1000000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", " N", " N", " N", " Tr", " Tr", " Tr", " Tỷ", " Tỷ", " Tỷ", " NT", " NT", " NT"}); - CompactDecimalFormat.add("zh", - new long[]{1L, 1L, 1L, 1L, 10000L, 10000L, 10000L, 10000L, 100000000L, 100000000L, 100000000L, 100000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "万", "万", "万", "万", "亿", "亿", "亿", "亿", "兆", "兆", "兆"}); - CompactDecimalFormat.add("zh_Hant", - new long[]{1L, 1L, 1L, 1L, 10000L, 10000L, 10000L, 10000L, 100000000L, 100000000L, 100000000L, 100000000L, 1000000000000L, 1000000000000L, 1000000000000L}, - new String[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, - new String[]{"", "", "", "", "萬", "萬", "萬", "萬", "億", "億", "億", "億", "兆", "兆", "兆"}); -}} diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java index f35e0bc307e..7cf02476770 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java @@ -13,7 +13,7 @@ import com.ibm.icu.text.NumberFormat.CompactStyle; import com.ibm.icu.util.ULocale; public class CompactDecimalFormatTest extends TestFmwk { - + public static void main(String[] args) { new CompactDecimalFormatTest().run(args); } @@ -37,7 +37,7 @@ public class CompactDecimalFormatTest extends TestFmwk { {123456789012345f, "120T"}, {12345678901234567890f, "12000000T"}, }; - + Object[][] JapaneseTestData = { {1234, "1200"}, {12345, "1.2万"}, @@ -53,6 +53,21 @@ public class CompactDecimalFormatTest extends TestFmwk { {123456789012345f, "120兆"}, }; + Object[][] SwahiliTestData = { + {1234, "elfu\u00a01.2"}, + {12345, "elfu\u00a012"}, + {123456, "laki1.2"}, + {1234567, "M1.2"}, + {12345678, "M12"}, + {123456789, "M120"}, + {1234567890, "B1.2"}, + {12345678901f, "B12"}, + {123456789012f, "B120"}, + {1234567890123f, "T1.2"}, + {12345678901234f, "T12"}, + {12345678901234567890f, "T12000000"}, + }; + public void TestEnglish() { checkLocale(ULocale.ENGLISH, EnglishTestData); } @@ -66,10 +81,14 @@ public class CompactDecimalFormatTest extends TestFmwk { checkLocale(ULocale.forLanguageTag("ja-DE"), JapaneseTestData); } + public void TestSwahili() { + checkLocale(ULocale.forLanguageTag("sw"), SwahiliTestData); + } + public void checkLocale(ULocale locale, Object[][] testData) { CompactDecimalFormat cdf = NumberFormat.getCompactDecimalInstance(locale, CompactStyle.SHORT); for (Object[] row : testData) { - assertEquals(locale + " (" + locale.getDisplayName(locale) + ")", row[1], cdf.format((Number) row[0])); + assertEquals(locale + " (" + locale.getDisplayName(locale) + ")", row[1], cdf.format(row[0])); } } }