ICU-8460 Add initial version, @internal for now.

X-SVN-Rev: 31450
This commit is contained in:
Mark Davis 2012-02-20 22:13:20 +00:00
parent 20e8036d10
commit f1c787eca1
6 changed files with 596 additions and 5 deletions

3
.gitattributes vendored
View file

@ -245,6 +245,8 @@ 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/CompactDecimalFormat.java -text
icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormatData.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
@ -304,6 +306,7 @@ icu4j/main/tests/core/manifest.stub -text
icu4j/main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict -text
icu4j/main/tests/core/src/com/ibm/icu/dev/data/resources/testmessages.properties -text
icu4j/main/tests/core/src/com/ibm/icu/dev/data/thai6.ucs -text
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java -text
icu4j/main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.impl.OlsonTimeZone.dat -text
icu4j/main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.impl.TimeZoneAdapter.dat -text
icu4j/main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.math.BigDecimal.dat -text

View file

@ -0,0 +1,240 @@
/*
*******************************************************************************
* Copyright (C) 1996-2012, Google, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.text;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.ibm.icu.util.ULocale;
/**
* The CompactDecimalFormat produces abbreviated numbers, suitable for display in environments will limited real estate.
* For example, 'Hits: 1.2B' instead of 'Hits: 1,200,000,000'. The format will be appropriate for the given language,
* such as "1,2 Mrd." for German.
* <p>
* For numbers under 1000 trillion (under 10^15, such as 123,456,789,012,345), the result will be short for supported
* languages. However, the result may sometimes exceed 7 characters, such as when there are combining marks or thin
* characters. In such cases, the visual width in fonts should still be short.
* <p>
* By default, there are 2 significant digits. After creation, if more than three significant digits are set (with
* setMaximumSignificantDigits), or if a fixed number of digits are set (with setMaximumIntegerDigits or
* setMaximumFractionDigits), then result may be wider.
* <p>
* At this time, negative numbers and parsing are not supported, and will produce an UnsupportedOperationException.
* Resetting the pattern prefixes or suffixes is not supported; the method calls are ignored.
* <p>
* Note that important methods, like setting the number of decimals, will be moved up from DecimalFormat to
* NumberFormat.
*
* @author markdavis
* @internal
*/
public class CompactDecimalFormat extends DecimalFormat {
private static final long serialVersionUID = 4716293295276629682L;
private static final int MINIMUM_ARRAY_LENGTH = 15;
private static final int POSITIVE_PREFIX = 0, POSITIVE_SUFFIX = 1, AFFIX_SIZE = 2;
private final String[] prefix;
private final String[] suffix;
private final long[] divisor;
private final String[] currencyAffixes;
/**
* The normal mechanism is to use NumberFormat.getCompactDecimalInstance(). This is intended only for testing.
*
* @param locale
* the desired locale
* @param style
* the compact style
* @internal
*/
public 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();
}
this.prefix = data.prefixes;
this.suffix = data.suffixes;
this.divisor = data.divisors;
applyPattern(format.toPattern());
setDecimalFormatSymbols(format.getDecimalFormatSymbols());
setMaximumSignificantDigits(2); // default significant digits
setSignificantDigitsUsed(true);
setGroupingUsed(false);
DecimalFormat currencyFormat = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
currencyAffixes = new String[AFFIX_SIZE];
currencyAffixes[CompactDecimalFormat.POSITIVE_PREFIX] = currencyFormat.getPositivePrefix();
currencyAffixes[CompactDecimalFormat.POSITIVE_SUFFIX] = currencyFormat.getPositiveSuffix();
// TODO fix to get right symbol for the count
}
/**
* Create a short number "from scratch". Intended for internal use. The prefix, suffix, and divisor arrays are
* 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.
* @param formatSymbols
* Decimal format symbols, typically from a locale.
* @param prefix
* An array of prefix values, one for each power of 10 from 0 to 14
* @param suffix
* An array of prefix values, one for each power of 10 from 0 to 14
* @param divisor
* An array of prefix values, one for each power of 10 from 0 to 14
* @param debugCreationErrors
* A collection of strings for debugging. If null on input, then any errors found will be added to that
* collection instead of throwing exceptions.
* @internal
*/
public CompactDecimalFormat(String pattern, DecimalFormatSymbols formatSymbols, String[] prefix, String[] suffix,
long[] divisor, Collection<String> debugCreationErrors, CompactStyle style, String[] currencyAffixes) {
if (prefix.length < MINIMUM_ARRAY_LENGTH) {
recordError(debugCreationErrors, "Must have at least " + MINIMUM_ARRAY_LENGTH + " prefix items.");
}
if (prefix.length != suffix.length || prefix.length != divisor.length) {
recordError(debugCreationErrors, "Prefix, suffix, and divisor arrays must have the same length.");
}
long oldDivisor = 0;
Map<String, Integer> seen = new HashMap<String, Integer>();
for (int i = 0; i < prefix.length; ++i) {
if (prefix[i] == null || suffix[i] == null) {
recordError(debugCreationErrors, "Prefix or suffix is null for " + i);
}
// divisor must be a power of 10, and must be less than or equal to 10^i
int log = (int) Math.log10(divisor[i]);
if (log > i) {
recordError(debugCreationErrors, "Divisor[" + i + "] must be less than or equal to 10^" + i
+ ", but is: " + divisor[i]);
}
long roundTrip = (long) Math.pow(10.0d, log);
if (roundTrip != divisor[i]) {
recordError(debugCreationErrors, "Divisor[" + i + "] must be a power of 10, but is: " + divisor[i]);
}
// we can't have two different indexes with the same display
String key = prefix[i] + "\uFFFF" + suffix[i] + "\uFFFF" + (i - log);
Integer old = seen.get(key);
if (old != null) {
recordError(debugCreationErrors, "Collision between values for " + i + " and " + old
+ " for [prefix/suffix/index-log(divisor)" + key.replace('\uFFFF', ';'));
} else {
seen.put(key, i);
}
if (divisor[i] < oldDivisor) {
recordError(debugCreationErrors, "Bad divisor, the divisor for 10E" + i + "(" + divisor[i]
+ ") is less than the divisor for the divisor for 10E" + (i - 1) + "(" + oldDivisor + ")");
}
oldDivisor = divisor[i];
}
this.prefix = prefix.clone();
this.suffix = suffix.clone();
this.divisor = divisor.clone();
applyPattern(pattern);
setDecimalFormatSymbols(formatSymbols);
setMaximumSignificantDigits(2); // default significant digits
setSignificantDigitsUsed(true);
setGroupingUsed(false);
this.currencyAffixes = currencyAffixes.clone();
}
@Override
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
if (number < 0.0d) {
throw new UnsupportedOperationException("CompactDecimalFormat doesn't handle negative numbers yet.");
}
int integerCount = (int) Math.log10(number);
int base = integerCount > 14 ? 14 : integerCount;
number = number / divisor[base];
setPositivePrefix(prefix[base]);
setPositiveSuffix(suffix[base]);
setCurrency(null);
return super.format(number, toAppendTo, pos);
}
@Override
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
return format((double) number, toAppendTo, pos);
}
@Override
public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
return format(number.doubleValue(), toAppendTo, pos);
}
@Override
public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
return format(number.doubleValue(), toAppendTo, pos);
}
@Override
public StringBuffer format(com.ibm.icu.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
return format(number.doubleValue(), toAppendTo, pos);
}
/**
* Parsing is currently unsupported, and throws an UnsupportedOperationException.
*/
@Override
public Number parse(String text, ParsePosition parsePosition) {
throw new UnsupportedOperationException();
}
/* INTERNALS */
private static ULocale zhTW = new ULocale("zh_TW");
private void recordError(Collection<String> creationErrors, String errorMessage) {
if (creationErrors == null) {
throw new IllegalArgumentException(errorMessage);
}
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<ULocale, Data> localeToData = new HashMap<ULocale, Data>();
static void add(String locale, long[] ls, String[] prefixes, String[] suffixes) {
localeToData.put(new ULocale(locale), new Data(ls, prefixes, suffixes));
}
static {
CompactDecimalFormatData.load();
}
}

View file

@ -0,0 +1,234 @@
/*
*******************************************************************************
* 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[]{"", "", "", "", "", "", "", "", "", "", "", "", "", "", ""});
}}

View file

@ -713,6 +713,46 @@ public abstract class NumberFormat extends UFormat {
return getInstance(inLocale, SCIENTIFICSTYLE);
}
/**
* Style parameter for CompactDecimalFormat.
* @internal
*/
public enum CompactStyle {
/**
* Short version, like "1.2T"
*/
SHORT,
/**
* Longer version, like "1.2 trillion", if available. May return same result as SHORT if not.
*/
LONG
}
/**
* Create a CompactDecimalFormat appropriate for a locale (Mockup for what would be in NumberFormat). The result may
* be affected by the number system in the locale, such as ar-u-nu-latn.
*
* @param locale the desired locale
* @param style the compact style
* @internal
*/
public static final CompactDecimalFormat getCompactDecimalInstance(ULocale locale, CompactStyle style) {
return new CompactDecimalFormat(locale, style);
}
/**
* Create a CompactDecimalFormat appropriate for a locale (Mockup for what would be in NumberFormat). The result may
* be affected by the number system in the locale, such as ar-u-nu-latn.
*
* @param locale the desired locale
* @param style the compact style
* @internal
*/
public static final CompactDecimalFormat getCompactDecimalInstance(Locale locale, CompactStyle style) {
return new CompactDecimalFormat(ULocale.forLocale(locale), style);
}
// ===== Factory stuff =====
/**
* A NumberFormatFactory is used to register new number formats. The factory
@ -1796,4 +1836,4 @@ public abstract class NumberFormat extends UFormat {
throw new InvalidObjectException("An invalid object.");
}
}
}
}

View file

@ -0,0 +1,71 @@
/*
*******************************************************************************
* Copyright (C) 1996-2012, Google, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.test.format;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.CompactDecimalFormat;
import com.ibm.icu.text.NumberFormat;
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);
}
Object[][] EnglishTestData = {
// default is 2 digits of accuracy
{1234, "1.2K"},
{12345, "12K"},
{123456, "120K"},
{1234567, "1.2M"},
{12345678, "12M"},
{123456789, "120M"},
{1234567890, "1.2B"},
{12345678901f, "12B"},
{123456789012f, "120B"},
{1234567890123f, "1.2T"},
{12345678901234f, "12T"},
{123456789012345f, "120T"},
};
Object[][] JapaneseTestData = {
{1234, "1200"},
{12345, "1.2万"},
{123456, "12万"},
{1234567, "120万"},
{12345678, "1200万"},
{123456789, "1.2億"},
{1234567890, "12億"},
{12345678901f, "120億"},
{123456789012f, "1200億"},
{1234567890123f, "1.2兆"},
{12345678901234f, "12兆"},
{123456789012345f, "120兆"},
};
public void TestEnglish() {
checkLocale(ULocale.ENGLISH, EnglishTestData);
}
public void TestJapanese() {
checkLocale(ULocale.JAPANESE, JapaneseTestData);
}
public void TestJapaneseGermany() {
// check fallback.
checkLocale(ULocale.forLanguageTag("ja-DE"), JapaneseTestData);
}
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]));
}
}
}

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (c) 2002-2011, International Business Machines
* Copyright (c) 2002-2012, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Mark Davis
@ -199,9 +199,12 @@ public class Relation<K, V> implements Freezable { // TODO: add , Map<K, Collect
}
public Set<V> values() {
Set<V> result = newSet();
for (K key : data.keySet()) {
result.addAll(data.get(key));
return values(new LinkedHashSet());
}
public <C extends Collection<V>> C values(C result) {
for (Entry<K, Set<V>> keyValue : data.entrySet()) {
result.addAll(keyValue.getValue());
}
return result;
}