3 *******************************************************************************
4 * Copyright (C) 2001-2011, International Business Machines Corporation and *
5 * others. All Rights Reserved. *
6 *******************************************************************************
10 * Port From: ICU4C v1.8.1 : format : NumberFormatTest
11 * Source File: $ICU4CRoot/source/test/intltest/numfmtst.cpp
14 package com.ibm.icu.dev.test.format;
16 import java.math.BigInteger;
17 import java.text.FieldPosition;
18 import java.text.ParseException;
19 import java.text.ParsePosition;
20 import java.util.ArrayList;
21 import java.util.Locale;
24 import com.ibm.icu.dev.test.TestUtil;
25 import com.ibm.icu.impl.LocaleUtility;
26 import com.ibm.icu.impl.Utility;
27 import com.ibm.icu.impl.data.ResourceReader;
28 import com.ibm.icu.impl.data.TokenIterator;
29 import com.ibm.icu.math.BigDecimal;
30 import com.ibm.icu.math.MathContext;
31 import com.ibm.icu.text.DecimalFormat;
32 import com.ibm.icu.text.DecimalFormatSymbols;
33 import com.ibm.icu.text.MeasureFormat;
34 import com.ibm.icu.text.NumberFormat;
35 import com.ibm.icu.text.NumberFormat.NumberFormatFactory;
36 import com.ibm.icu.text.NumberFormat.SimpleNumberFormatFactory;
37 import com.ibm.icu.util.Currency;
38 import com.ibm.icu.util.CurrencyAmount;
39 import com.ibm.icu.util.ULocale;
41 public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
43 public static void main(String[] args) throws Exception {
44 new NumberFormatTest().run(args);
47 // Test various patterns
48 public void TestPatterns() {
50 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
51 final String pat[] = { "#.#", "#.", ".#", "#" };
52 int pat_length = pat.length;
53 final String newpat[] = { "#0.#", "#0.", "#.0", "#" };
54 final String num[] = { "0", "0.", ".0", "0" };
55 for (int i=0; i<pat_length; ++i)
57 DecimalFormat fmt = new DecimalFormat(pat[i], sym);
58 String newp = fmt.toPattern();
59 if (!newp.equals(newpat[i]))
60 errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
61 "; " + newp + " seen instead");
63 String s = ((NumberFormat)fmt).format(0);
64 if (!s.equals(num[i]))
66 errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
67 "; " + s + " seen instead");
68 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
70 // BigInteger 0 - ticket#4731
71 s = ((NumberFormat)fmt).format(BigInteger.ZERO);
72 if (!s.equals(num[i]))
74 errln("FAIL: Pattern " + pat[i] + " should format BigInteger zero as " + num[i] +
75 "; " + s + " seen instead");
76 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
81 // Test exponential pattern
82 public void TestExponential() {
84 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
85 final String pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
86 int pat_length = pat.length;
88 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
89 int val_length = val.length;
90 final String valFormat[] = {
92 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
94 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
96 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
98 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" };
101 0.01234, 123460000, 1.23E300, -3.1416E-271,
102 0.01234, 123460000, 1.23E300, -3.1416E-271,
103 0.01234, 123456800, 1.23E300, -3.141593E-271,
104 0.01234, 123500000, 1.23E300, -3.142E-271,
105 };*/ //The variable is never used
107 int lval[] = { 0, -1, 1, 123456789 };
108 int lval_length = lval.length;
109 final String lvalFormat[] = {
111 "0E0", "-1E0", "1E0", "1.2346E8",
113 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
115 "0E000", "-1E000", "1E000", "123.4568E006",
117 "0E0", "[1E0]", "1E0", "1.235E8" };
125 int ival = 0, ilval = 0;
126 for (int p = 0; p < pat_length; ++p) {
127 DecimalFormat fmt = new DecimalFormat(pat[p], sym);
128 logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" + fmt.toPattern() + "\"");
130 for (v = 0; v < val_length; ++v) {
132 s = ((NumberFormat) fmt).format(val[v]);
133 logln(" " + val[v] + " -format-> " + s);
134 if (!s.equals(valFormat[v + ival]))
135 errln("FAIL: Expected " + valFormat[v + ival]);
137 ParsePosition pos = new ParsePosition(0);
138 double a = fmt.parse(s, pos).doubleValue();
139 if (pos.getIndex() == s.length()) {
140 logln(" -parse-> " + Double.toString(a));
141 // Use epsilon comparison as necessary
143 errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
145 for (v = 0; v < lval_length; ++v) {
147 s = ((NumberFormat) fmt).format(lval[v]);
148 logln(" " + lval[v] + "L -format-> " + s);
149 if (!s.equals(lvalFormat[v + ilval]))
150 errln("ERROR: Expected " + lvalFormat[v + ilval] + " Got: " + s);
152 ParsePosition pos = new ParsePosition(0);
154 Number A = fmt.parse(s, pos);
157 if (pos.getIndex() == s.length()) {
158 logln(" -parse-> " + a);
159 if (a != lvalParse[v + ilval])
160 errln("FAIL: Expected " + lvalParse[v + ilval]);
162 errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + Long.toString(a));
164 errln("Fail to parse the string: " + s);
168 ilval += lval_length;
172 // Test the handling of quotes
173 public void TestQuotes() {
176 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
177 pat = new StringBuffer("a'fo''o'b#");
178 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
179 String s = ((NumberFormat)fmt).format(123);
180 logln("Pattern \"" + pat + "\"");
181 logln(" Format 123 . " + s);
182 if (!s.equals("afo'ob123"))
183 errln("FAIL: Expected afo'ob123");
186 pat = new StringBuffer("a''b#");
187 fmt = new DecimalFormat(pat.toString(), sym);
188 s = ((NumberFormat)fmt).format(123);
189 logln("Pattern \"" + pat + "\"");
190 logln(" Format 123 . " + s);
191 if (!s.equals("a'b123"))
192 errln("FAIL: Expected a'b123");
195 public void TestParseCurrencyTrailingSymbol() {
196 // see sun bug 4709840
197 NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
198 float val = 12345.67f;
199 String str = fmt.format(val);
200 logln("val: " + val + " str: " + str);
202 Number num = fmt.parse(str);
203 logln("num: " + num);
204 } catch (ParseException e) {
205 errln("parse of '" + str + "' threw exception: " + e);
210 * Test the handling of the currency symbol in patterns.
212 public void TestCurrencySign() {
213 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
214 StringBuffer pat = new StringBuffer("");
215 char currency = 0x00A4;
216 // "\xA4#,##0.00;-\xA4#,##0.00"
217 pat.append(currency).append("#,##0.00;-").append(currency).append("#,##0.00");
218 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
219 String s = ((NumberFormat) fmt).format(1234.56);
220 pat = new StringBuffer();
221 logln("Pattern \"" + fmt.toPattern() + "\"");
222 logln(" Format " + 1234.56 + " . " + s);
223 assertEquals("symbol, pos", "$1,234.56", s);
225 s = ((NumberFormat) fmt).format(-1234.56);
226 logln(" Format " + Double.toString(-1234.56) + " . " + s);
227 assertEquals("symbol, neg", "-$1,234.56", s);
230 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
231 pat.append(currency).append(currency).append(" #,##0.00;").append(currency).append(currency).append(" -#,##0.00");
232 fmt = new DecimalFormat(pat.toString(), sym);
233 s = ((NumberFormat) fmt).format(1234.56);
234 logln("Pattern \"" + fmt.toPattern() + "\"");
235 logln(" Format " + Double.toString(1234.56) + " . " + s);
236 assertEquals("name, pos", "USD 1,234.56", s);
238 s = ((NumberFormat) fmt).format(-1234.56);
239 logln(" Format " + Double.toString(-1234.56) + " . " + s);
240 assertEquals("name, neg", "USD -1,234.56", s);
243 public void TestSpaceParsing() {
245 // the string to be parsed, parsed position, parsed error index
248 {"$124 $124", "4", "-1"},
249 {"$124 ", "4", "-1"},
250 {"$ 124 ", "5", "-1"},
251 {"$\u00A0124 ", "5", "-1"},
252 {" $ 124 ", "0", "0"}, // TODO: need to handle space correctly
253 {"124$", "0", "3"}, // TODO: need to handle space correctly
254 // {"124 $", "5", "-1"}, TODO: OK or NOT?
257 NumberFormat foo = NumberFormat.getCurrencyInstance();
258 for (int i = 0; i < DATA.length; ++i) {
259 ParsePosition parsePosition = new ParsePosition(0);
260 String stringToBeParsed = DATA[i][0];
261 int parsedPosition = Integer.parseInt(DATA[i][1]);
262 int errorIndex = Integer.parseInt(DATA[i][2]);
264 Number result = foo.parse(stringToBeParsed, parsePosition);
265 if (parsePosition.getIndex() != parsedPosition ||
266 parsePosition.getErrorIndex() != errorIndex) {
267 errln("FAILED parse " + stringToBeParsed + "; parse position: " + parsePosition.getIndex() + "; error position: " + parsePosition.getErrorIndex());
269 if (parsePosition.getErrorIndex() == -1 &&
270 result.doubleValue() != 124) {
271 errln("FAILED parse " + stringToBeParsed + "; value " + result.doubleValue());
273 } catch (Exception e) {
274 errln("FAILED " + e.toString());
280 public void TestMultiCurrencySign() {
282 // the fields in the following test are:
284 // currency pattern (with negative pattern),
285 // currency number to be formatted,
286 // currency format using currency symbol name, such as "$" for USD,
287 // currency format using currency ISO name, such as "USD",
288 // currency format using plural name, such as "US dollars".
290 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"},
291 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
292 {"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollar1.00"},
294 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY1,234.56", "\u4EBA\u6C11\u5E011,234.56"},
295 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY1,234.56)", "(\u4EBA\u6C11\u5E011,234.56)"},
296 {"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY1.00", "\u4EBA\u6C11\u5E011.00"}
299 String doubleCurrencyStr = "\u00A4\u00A4";
300 String tripleCurrencyStr = "\u00A4\u00A4\u00A4";
302 for (int i=0; i<DATA.length; ++i) {
303 String locale = DATA[i][0];
304 String pat = DATA[i][1];
305 Double numberToBeFormat = new Double(DATA[i][2]);
306 DecimalFormatSymbols sym = new DecimalFormatSymbols(new ULocale(locale));
307 for (int j=1; j<=3; ++j) {
308 // j represents the number of currency sign in the pattern.
310 pat = pat.replaceAll("\u00A4", doubleCurrencyStr);
312 pat = pat.replaceAll("\u00A4\u00A4", tripleCurrencyStr);
314 DecimalFormat fmt = new DecimalFormat(pat, sym);
315 String s = ((NumberFormat) fmt).format(numberToBeFormat);
316 // DATA[i][3] is the currency format result using a
317 // single currency sign.
318 // DATA[i][4] is the currency format result using
319 // double currency sign.
320 // DATA[i][5] is the currency format result using
321 // triple currency sign.
322 // DATA[i][j+2] is the currency format result using
323 // 'j' number of currency sign.
324 String currencyFormatResult = DATA[i][2+j];
325 if (!s.equals(currencyFormatResult)) {
326 errln("FAIL format: Expected " + currencyFormatResult);
330 for (int k=3; k<=5; ++k) {
331 // DATA[i][3] is the currency format result using a
332 // single currency sign.
333 // DATA[i][4] is the currency format result using
334 // double currency sign.
335 // DATA[i][5] is the currency format result using
336 // triple currency sign.
337 String oneCurrencyFormat = DATA[i][k];
338 if (fmt.parse(oneCurrencyFormat).doubleValue() !=
339 numberToBeFormat.doubleValue()) {
340 errln("FAILED parse " + oneCurrencyFormat);
343 } catch (ParseException e) {
344 errln("FAILED, DecimalFormat parse currency: " + e.toString());
350 public void TestCurrencyFormatForMixParsing() {
351 MeasureFormat curFmt = MeasureFormat.getCurrencyFormat(new ULocale("en_US"));
353 "$1,234.56", // string to be parsed
355 "US dollars1,234.56",
356 "1,234.56 US dollars"
359 for (int i = 0; i < formats.length; ++i) {
360 String stringToBeParsed = formats[i];
361 CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(stringToBeParsed);
362 Number val = parsedVal.getNumber();
363 if (!val.equals(new BigDecimal("1234.56"))) {
364 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val);
366 if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) {
367 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency");
370 } catch (ParseException e) {
371 errln("parse FAILED: " + e.toString());
375 public void TestDecimalFormatCurrencyParse() {
377 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
378 StringBuffer pat = new StringBuffer("");
379 char currency = 0x00A4;
380 // "\xA4#,##0.00;-\xA4#,##0.00"
381 pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
382 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
385 // string to be parsed, the parsed result (number)
388 {"1.00 US dollar", "1"},
389 {"$1,234.56", "1234.56"},
390 {"USD1,234.56", "1234.56"},
391 {"1,234.56 US dollar", "1234.56"},
394 for (int i = 0; i < DATA.length; ++i) {
395 String stringToBeParsed = DATA[i][0];
396 double parsedResult = Double.parseDouble(DATA[i][1]);
397 Number num = fmt.parse(stringToBeParsed);
398 if (num.doubleValue() != parsedResult) {
399 errln("FAIL parse: Expected " + parsedResult);
402 } catch (ParseException e) {
403 errln("FAILED, DecimalFormat parse currency: " + e.toString());
408 * Test localized currency patterns.
410 public void TestCurrency() {
412 "fr", "CA", "", "1,50\u00a0$",
413 "de", "DE", "", "1,50\u00a0\u20AC",
414 "de", "DE", "PREEURO", "1,50\u00a0DEM",
415 "fr", "FR", "", "1,50\u00a0\u20AC",
416 "fr", "FR", "PREEURO", "1,50\u00a0F",
419 for (int i=0; i<DATA.length; i+=4) {
420 Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
421 NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
422 String s = fmt.format(1.50);
423 if (s.equals(DATA[i+3])) {
424 logln("Ok: 1.50 x " + locale + " => " + s);
426 logln("FAIL: 1.50 x " + locale + " => " + s +
427 ", expected " + DATA[i+3]);
431 // format currency with CurrencyAmount
432 for (int i=0; i<DATA.length; i+=4) {
433 Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
435 Currency curr = Currency.getInstance(locale);
436 logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
437 CurrencyAmount cAmt = new CurrencyAmount(1.5, curr);
438 logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
440 NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
441 String sCurr = fmt.format(cAmt);
442 if (sCurr.equals(DATA[i+3])) {
443 logln("Ok: 1.50 x " + locale + " => " + sCurr);
445 errln("FAIL: 1.50 x " + locale + " => " + sCurr +
446 ", expected " + DATA[i+3]);
450 //Cover MeasureFormat.getCurrencyFormat()
451 ULocale save = ULocale.getDefault();
452 ULocale.setDefault(ULocale.US);
453 MeasureFormat curFmt = MeasureFormat.getCurrencyFormat();
454 String strBuf = curFmt.format(new CurrencyAmount(new Float(1234.56), Currency.getInstance("USD")));
457 CurrencyAmount parsedVal = (CurrencyAmount)curFmt.parseObject(strBuf);
458 Number val = parsedVal.getNumber();
459 if (!val.equals(new BigDecimal("1234.56"))) {
460 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number. val=" + val);
462 if (!parsedVal.getCurrency().equals(Currency.getInstance("USD"))) {
463 errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the currency");
466 catch (ParseException e) {
467 errln("FAIL: " + e.getMessage());
469 ULocale.setDefault(save);
472 public void TestCurrencyIsoPluralFormat() {
476 // currency amount to be formatted,
477 // currency ISO code to be formatted,
478 // format result using CURRENCYSTYLE,
479 // format result using ISOCURRENCYSTYLE,
480 // format result using PLURALCURRENCYSTYLE,
481 {"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollar"},
482 {"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
483 {"en_US", "-1234.56", "USD", "($1,234.56)", "(USD1,234.56)", "-1,234.56 US dollars"},
484 {"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00 \u7F8E\u5143"},
485 {"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56 \u7F8E\u5143"},
486 //{"zh_CN", "1", "CHY", "CHY1.00", "CHY1.00", "1.00 CHY"},
487 //{"zh_CN", "1234.56", "CHY", "CHY1,234.56", "CHY1,234.56", "1,234.56 CHY"},
488 {"zh_CN", "1", "CNY", "\uFFE51.00", "CNY1.00", "1.00 \u4EBA\u6C11\u5E01"},
489 {"zh_CN", "1234.56", "CNY", "\uFFE51,234.56", "CNY1,234.56", "1,234.56 \u4EBA\u6C11\u5E01"},
490 {"ru_RU", "1", "RUB", "1,00\u00A0\u0440\u0443\u0431.", "1,00\u00A0RUB", "1,00 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0439 \u0440\u0443\u0431\u043B\u044C"},
491 {"ru_RU", "2", "RUB", "2,00\u00A0\u0440\u0443\u0431.", "2,00\u00A0RUB", "2,00 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u044F"},
492 {"ru_RU", "5", "RUB", "5,00\u00A0\u0440\u0443\u0431.", "5,00\u00A0RUB", "5,00 \u0440\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u0435\u0439"},
493 // test locale without currency information
494 {"root", "-1.23", "USD", "-US$\u00a01.23", "-USD\u00a01.23", "-1.23 USD"},
495 {"root@numbers=latn", "-1.23", "USD", "-US$\u00a01.23", "-USD\u00a01.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers
496 {"root@numbers=arab", "-1.23", "USD", "-US$\u00a0\u0661\u066B\u0662\u0663", "-USD\u00a0\u0661\u066B\u0662\u0663", "-\u0661\u066B\u0662\u0663 USD"}, // ensure that the root locale is still used with modifiers
497 // test choice format
498 {"es_AR", "1", "INR", "\u20B91,00", "INR1,00", "1,00 rupia india"},
499 {"ar_EG", "1", "USD", "US$\u00A0\u0661\u066B\u0660\u0660", "USD\u00a0\u0661\u066b\u0660\u0660", "\u0661\u066b\u0660\u0660 \u062f\u0648\u0644\u0627\u0631 \u0623\u0645\u0631\u064a\u0643\u064a"},
502 for (int i=0; i<DATA.length; ++i) {
503 for (int k = NumberFormat.CURRENCYSTYLE;
504 k <= NumberFormat.PLURALCURRENCYSTYLE;
506 // k represents currency format style.
507 if ( k != NumberFormat.CURRENCYSTYLE &&
508 k != NumberFormat.ISOCURRENCYSTYLE &&
509 k != NumberFormat.PLURALCURRENCYSTYLE ) {
512 String localeString = DATA[i][0];
513 Double numberToBeFormat = new Double(DATA[i][1]);
514 String currencyISOCode = DATA[i][2];
515 ULocale locale = new ULocale(localeString);
516 NumberFormat numFmt = NumberFormat.getInstance(locale, k);
517 numFmt.setCurrency(Currency.getInstance(currencyISOCode));
518 String strBuf = numFmt.format(numberToBeFormat);
519 int resultDataIndex = k-1;
520 if ( k == NumberFormat.CURRENCYSTYLE ) {
521 resultDataIndex = k+2;
523 // DATA[i][resultDataIndex] is the currency format result
524 // using 'k' currency style.
525 String formatResult = DATA[i][resultDataIndex];
526 if (!strBuf.equals(formatResult)) {
527 errln("FAIL: Expected " + formatResult + " actual: " + Utility.escape(strBuf));
530 // test parsing, and test parsing for all currency formats.
531 for (int j = 3; j < 6; ++j) {
532 // DATA[i][3] is the currency format result using
533 // CURRENCYSTYLE formatter.
534 // DATA[i][4] is the currency format result using
535 // ISOCURRENCYSTYLE formatter.
536 // DATA[i][5] is the currency format result using
537 // PLURALCURRENCYSTYLE formatter.
538 String oneCurrencyFormatResult = DATA[i][j];
539 Number val = numFmt.parse(oneCurrencyFormatResult);
540 if (val.doubleValue() != numberToBeFormat.doubleValue()) {
541 errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat);
545 catch (ParseException e) {
546 errln("FAIL: " + e.getMessage());
553 public void TestMiscCurrencyParsing() {
555 // each has: string to be parsed, parsed position, error position
557 {"1.00 UAE dirha", "0", "4"},
558 {"1.00 us dollar", "14", "-1"},
559 {"1.00 US DOLLAR", "14", "-1"},
560 {"1.00 usd", "0", "4"},
562 ULocale locale = new ULocale("en_US");
563 for (int i=0; i<DATA.length; ++i) {
564 String stringToBeParsed = DATA[i][0];
565 int parsedPosition = Integer.parseInt(DATA[i][1]);
566 int errorIndex = Integer.parseInt(DATA[i][2]);
567 NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
568 ParsePosition parsePosition = new ParsePosition(0);
569 Number val = numFmt.parse(stringToBeParsed, parsePosition);
570 if (parsePosition.getIndex() != parsedPosition ||
571 parsePosition.getErrorIndex() != errorIndex) {
572 errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex());
573 errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex());
575 if (parsePosition.getErrorIndex() == -1 &&
576 val.doubleValue() != 1.00) {
577 errln("FAIL: parse failed. expected 1.00, actual:" + val);
582 public void TestParseCurrency() {
583 class ParseCurrencyItem {
584 private String localeString;
585 private String descrip;
586 private String currStr;
587 private int numExpectPos;
588 private int numExpectVal;
589 private int curExpectPos;
590 private int curExpectVal;
591 private String curExpectCurr;
593 ParseCurrencyItem(String locStr, String desc, String curr, int numExPos, int numExVal, int curExPos, int curExVal, String curExCurr) {
594 localeString = locStr;
597 numExpectPos = numExPos;
598 numExpectVal = numExVal;
599 curExpectPos = curExPos;
600 curExpectVal = curExVal;
601 curExpectCurr = curExCurr;
603 public String getLocaleString() { return localeString; }
604 public String getDescrip() { return descrip; }
605 public String getCurrStr() { return currStr; }
606 public int getNumExpectPos() { return numExpectPos; }
607 public int getNumExpectVal() { return numExpectVal; }
608 public int getCurExpectPos() { return curExpectPos; }
609 public int getCurExpectVal() { return curExpectVal; }
610 public String getCurExpectCurr() { return curExpectCurr; }
612 final ParseCurrencyItem[] parseCurrencyItems = {
613 new ParseCurrencyItem( "en_US", "dollars2", "$2.00", 5, 2, 5, 2, "USD" ),
614 new ParseCurrencyItem( "en_US", "dollars4", "$4", 2, 4, 2, 4, "USD" ),
615 new ParseCurrencyItem( "en_US", "dollars9", "9\u00A0$", 0, 0, 0, 0, "" ),
616 new ParseCurrencyItem( "en_US", "pounds3", "\u00A33.00", 0, 0, 5, 3, "GBP" ),
617 new ParseCurrencyItem( "en_US", "pounds5", "\u00A35", 0, 0, 2, 5, "GBP" ),
618 new ParseCurrencyItem( "en_US", "pounds7", "7\u00A0\u00A3", 0, 0, 0, 0, "" ),
619 new ParseCurrencyItem( "en_US", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ),
621 new ParseCurrencyItem( "en_GB", "pounds3", "\u00A33.00", 5, 3, 5, 3, "GBP" ),
622 new ParseCurrencyItem( "en_GB", "pounds5", "\u00A35", 2, 5, 2, 5, "GBP" ),
623 new ParseCurrencyItem( "en_GB", "pounds7", "7\u00A0\u00A3", 0, 0, 0, 0, "" ),
624 new ParseCurrencyItem( "en_GB", "euros4", "4,00\u00A0\u20AC", 0, 0, 0, 0, "" ),
625 new ParseCurrencyItem( "en_GB", "euros6", "6\u00A0\u20AC", 0, 0, 0, 0, "" ),
626 new ParseCurrencyItem( "en_GB", "euros8", "\u20AC8", 0, 0, 2, 8, "EUR" ),
627 new ParseCurrencyItem( "en_GB", "dollars4", "$4", 0, 0, 2, 4, "USD" ),
629 new ParseCurrencyItem( "fr_FR", "euros4", "4,00\u00A0\u20AC", 6, 4, 6, 4, "EUR" ),
630 new ParseCurrencyItem( "fr_FR", "euros6", "6\u00A0\u20AC", 3, 6, 3, 6, "EUR" ),
631 new ParseCurrencyItem( "fr_FR", "euros8", "\u20AC8", 0, 0, 0, 0, "" ),
632 new ParseCurrencyItem( "fr_FR", "dollars2", "$2.00", 0, 0, 0, 0, "" ),
633 new ParseCurrencyItem( "fr_FR", "dollars4", "$4", 0, 0, 0, 0, "" ),
635 for (ParseCurrencyItem item: parseCurrencyItems) {
636 String localeString = item.getLocaleString();
637 ULocale uloc = new ULocale(localeString);
638 NumberFormat fmt = null;
640 fmt = NumberFormat.getCurrencyInstance(uloc);
641 } catch (Exception e) {
642 errln("NumberFormat.getCurrencyInstance fails for locale " + localeString);
645 String currStr = item.getCurrStr();
646 ParsePosition parsePos = new ParsePosition(0);
648 Number numVal = fmt.parse(currStr, parsePos);
649 if ( parsePos.getIndex() != item.getNumExpectPos() || (numVal != null && numVal.intValue() != item.getNumExpectVal()) ) {
650 if (numVal != null) {
651 errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() +
652 ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() +
653 ", get " + parsePos.getIndex() + "/" + numVal.intValue() );
655 errln("NumberFormat.getCurrencyInstance parse " + localeString + "/" + item.getDescrip() +
656 ", expect pos/val " + item.getNumExpectPos() + "/" + item.getNumExpectVal() +
657 ", get " + parsePos.getIndex() + "/(NULL)" );
661 parsePos.setIndex(0);
662 CurrencyAmount currAmt = fmt.parseCurrency(currStr, parsePos);
663 if ( parsePos.getIndex() != item.getCurExpectPos() || (currAmt != null && (currAmt.getNumber().intValue() != item.getCurExpectVal() ||
664 currAmt.getCurrency().getCurrencyCode().compareTo(item.getCurExpectCurr()) != 0)) ) {
665 if (currAmt != null) {
666 errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() +
667 ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() +
668 ", get " + parsePos.getIndex() + "/" + currAmt.getNumber().intValue() + "/" + currAmt.getCurrency().getCurrencyCode() );
670 errln("NumberFormat.getCurrencyInstance parseCurrency " + localeString + "/" + item.getDescrip() +
671 ", expect pos/val/curr " + item.getCurExpectPos() + "/" + item.getCurExpectVal() + "/" + item.getCurExpectCurr() +
672 ", get " + parsePos.getIndex() + "/(NULL)" );
679 * Test the Currency object handling, new as of ICU 2.2.
681 public void TestCurrencyObject() {
683 NumberFormat.getCurrencyInstance(Locale.US);
685 expectCurrency(fmt, null, 1234.56, "$1,234.56");
687 expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
688 1234.56, "\u20AC1,234.56"); // Euro
690 expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
691 1234.56, "\u00A51,235"); // Yen
693 expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
694 1234.56, "CHF1,234.55"); // 0.05 rounding
696 expectCurrency(fmt, Currency.getInstance(Locale.US),
697 1234.56, "$1,234.56");
699 fmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
701 expectCurrency(fmt, null, 1234.56, "1 234,56 \u20AC");
703 expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
704 1234.56, "1 235 \u00A5JP"); // Yen
706 expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
707 1234.56, "1 234,55 CHF"); // 0.25 rounding
709 expectCurrency(fmt, Currency.getInstance(Locale.US),
710 1234.56, "1 234,56 $US");
712 expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
713 1234.56, "1 234,56 \u20AC"); // Euro
716 public void TestCurrencyPatterns() {
718 Locale[] locs = NumberFormat.getAvailableLocales();
719 for (i=0; i<locs.length; ++i) {
720 NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]);
721 // Make sure currency formats do not have a variable number
722 // of fraction digits
723 int min = nf.getMinimumFractionDigits();
724 int max = nf.getMaximumFractionDigits();
726 String a = nf.format(1.0);
727 String b = nf.format(1.125);
728 errln("FAIL: " + locs[i] +
729 " min fraction digits != max fraction digits; "+
731 "; x 1.125 => " + b);
734 // Make sure EURO currency formats have exactly 2 fraction digits
735 if (nf instanceof DecimalFormat) {
736 Currency curr = ((DecimalFormat) nf).getCurrency();
737 if (curr != null && "EUR".equals(curr.getCurrencyCode())) {
738 if (min != 2 || max != 2) {
739 String a = nf.format(1.0);
740 errln("FAIL: " + locs[i] +
741 " is a EURO format but it does not have 2 fraction digits; "+
751 * Do rudimentary testing of parsing.
753 public void TestParse() {
755 DecimalFormat format = new DecimalFormat("00");
758 aNumber = format.parse(arg).doubleValue();
759 } catch (ParseException e) {
760 System.out.println(e);
762 logln("parse(" + arg + ") = " + aNumber);
766 * Test proper rounding by the format method.
768 public void TestRounding487() {
770 NumberFormat nf = NumberFormat.getInstance();
771 roundingTest(nf, 0.00159999, 4, "0.0016");
772 roundingTest(nf, 0.00995, 4, "0.01");
774 roundingTest(nf, 12.3995, 3, "12.4");
776 roundingTest(nf, 12.4999, 0, "12");
777 roundingTest(nf, - 19.5, 0, "-20");
782 * Test the functioning of the secondary grouping value.
784 public void TestSecondaryGrouping() {
786 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
787 DecimalFormat f = new DecimalFormat("#,##,###", US);
789 expect(f, 123456789L, "12,34,56,789");
790 expectPat(f, "#,##,###");
791 f.applyPattern("#,###");
793 f.setSecondaryGroupingSize(4);
794 expect(f, 123456789L, "12,3456,789");
795 expectPat(f, "#,####,###");
796 NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN"));
799 long l = 1876543210L;
802 // expect "1,87,65,43,210", but with Hindi digits
805 if (out.length() != 14) {
808 for (int i = 0; i < out.length(); ++i) {
809 boolean expectGroup = false;
818 // Later -- fix this to get the actual grouping
819 // character from the resource bundle.
820 boolean isGroup = (out.charAt(i) == 0x002C);
821 if (isGroup != expectGroup) {
828 errln("FAIL Expected "+ l + " x hi_IN . \"1,87,65,43,210\" (with Hindi digits), got \""
831 logln("Ok " + l + " x hi_IN . \"" + out + "\"");
835 public void roundingTest(NumberFormat nf, double x, int maxFractionDigits, final String expected) {
836 nf.setMaximumFractionDigits(maxFractionDigits);
837 String out = nf.format(x);
838 logln(x + " formats with " + maxFractionDigits + " fractional digits to " + out);
839 if (!out.equals(expected))
840 errln("FAIL: Expected " + expected);
844 * Upgrade to alphaWorks
846 public void TestExponent() {
847 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
848 DecimalFormat fmt1 = new DecimalFormat("0.###E0", US);
849 DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US);
851 expect2(fmt1, n, "1.234E3");
852 expect2(fmt2, n, "1.234E+3");
853 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
858 * Upgrade to alphaWorks
860 public void TestScientific() {
862 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
864 // Test pattern round-trip
865 final String PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
866 int PAT_length = PAT.length;
868 // min int, max int, min frac, max frac
870 1, 1, 0, 4, // "0.####E0"
871 2, 2, 3, 3, // "00.000E00"
872 1, 3, 0, 4, // "##0.####E000"
873 1, 1, 0, 3, // "0.###E0;[0.###E0]"
875 for (int i = 0; i < PAT_length; ++i) {
877 DecimalFormat df = new DecimalFormat(pat, US);
878 String pat2 = df.toPattern();
879 if (pat.equals(pat2)) {
880 logln("Ok Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
882 errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
884 // Make sure digit counts match what we expect
885 if (df.getMinimumIntegerDigits() != DIGITS[4 * i]
886 || df.getMaximumIntegerDigits() != DIGITS[4 * i + 1]
887 || df.getMinimumFractionDigits() != DIGITS[4 * i + 2]
888 || df.getMaximumFractionDigits() != DIGITS[4 * i + 3]) {
889 errln("FAIL \""+ pat+ "\" min/max int; min/max frac = "
890 + df.getMinimumIntegerDigits() + "/"
891 + df.getMaximumIntegerDigits() + ";"
892 + df.getMinimumFractionDigits() + "/"
893 + df.getMaximumFractionDigits() + ", expect "
894 + DIGITS[4 * i] + "/"
895 + DIGITS[4 * i + 1] + ";"
896 + DIGITS[4 * i + 2] + "/"
897 + DIGITS[4 * i + 3]);
901 expect2(new DecimalFormat("#E0", US), 12345.0, "1.2345E4");
902 expect(new DecimalFormat("0E0", US), 12345.0, "1E4");
904 // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
905 // so result = 1.234568E4 not 1.2345678901E4
906 //when the pattern problem is finalized, delete comment mark'//'
907 //of the following code
908 expect2(NumberFormat.getScientificInstance(Locale.US), 12345.678901, "1.2345678901E4");
909 logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
910 expect2(NumberFormat.getScientificInstance(ULocale.US), 12345.678901, "1.2345678901E4");
912 expect(new DecimalFormat("##0.###E0", US), 12345.0, "12.34E3");
913 expect(new DecimalFormat("##0.###E0", US), 12345.00001, "12.35E3");
914 expect2(new DecimalFormat("##0.####E0", US), 12345, "12.345E3");
916 // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
917 // so result = 1.234568E4 not 1.2345678901E4
918 expect2(NumberFormat.getScientificInstance(Locale.FRANCE), 12345.678901, "1,2345678901E4");
919 logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
920 expect2(NumberFormat.getScientificInstance(ULocale.FRANCE), 12345.678901, "1,2345678901E4");
922 expect(new DecimalFormat("##0.####E0", US), 789.12345e-9, "789.12E-9");
923 expect2(new DecimalFormat("##0.####E0", US), 780.e-9, "780E-9");
924 expect(new DecimalFormat(".###E0", US), 45678.0, ".457E5");
925 expect2(new DecimalFormat(".###E0", US), 0, ".0E0");
927 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
928 new DecimalFormat("##E0", US),
929 new DecimalFormat("####E0", US),
930 new DecimalFormat("0E0", US),
931 new DecimalFormat("00E0", US),
932 new DecimalFormat("000E0", US),
935 new String[] { "4.5678E7",
944 ! Unroll this test into individual tests below...
947 expect2(new DecimalFormat("#E0", US), 45678000, "4.5678E7");
948 expect2(new DecimalFormat("##E0", US), 45678000, "45.678E6");
949 expect2(new DecimalFormat("####E0", US), 45678000, "4567.8E4");
950 expect(new DecimalFormat("0E0", US), 45678000, "5E7");
951 expect(new DecimalFormat("00E0", US), 45678000, "46E6");
952 expect(new DecimalFormat("000E0", US), 45678000, "457E5");
954 expect(new DecimalFormat("###E0", US, status),
955 new Object[] { new Double(0.0000123), "12.3E-6",
956 new Double(0.000123), "123E-6",
957 new Double(0.00123), "1.23E-3",
958 new Double(0.0123), "12.3E-3",
959 new Double(0.123), "123E-3",
960 new Double(1.23), "1.23E0",
961 new Double(12.3), "12.3E0",
962 new Double(123), "123E0",
963 new Double(1230), "1.23E3",
966 ! Unroll this test into individual tests below...
969 expect2(new DecimalFormat("###E0", US), 0.0000123, "12.3E-6");
970 expect2(new DecimalFormat("###E0", US), 0.000123, "123E-6");
971 expect2(new DecimalFormat("###E0", US), 0.00123, "1.23E-3");
972 expect2(new DecimalFormat("###E0", US), 0.0123, "12.3E-3");
973 expect2(new DecimalFormat("###E0", US), 0.123, "123E-3");
974 expect2(new DecimalFormat("###E0", US), 1.23, "1.23E0");
975 expect2(new DecimalFormat("###E0", US), 12.3, "12.3E0");
976 expect2(new DecimalFormat("###E0", US), 123.0, "123E0");
977 expect2(new DecimalFormat("###E0", US), 1230.0, "1.23E3");
979 expect(new DecimalFormat("0.#E+00", US, status),
980 new Object[] { new Double(0.00012), "1.2E-04",
981 new Long(12000), "1.2E+04",
984 ! Unroll this test into individual tests below...
987 expect2(new DecimalFormat("0.#E+00", US), 0.00012, "1.2E-04");
988 expect2(new DecimalFormat("0.#E+00", US), 12000, "1.2E+04");
992 * Upgrade to alphaWorks
994 public void TestPad() {
996 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
997 expect2(new DecimalFormat("*^##.##", US), 0, "^^^^0");
998 expect2(new DecimalFormat("*^##.##", US), -1.3, "^-1.3");
1000 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
1002 "0.0E0______ g-m/s^2");
1004 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
1006 "333.333E-3_ g-m/s^2");
1007 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 0, "0.0______ g-m/s^2");
1009 new DecimalFormat("##0.0####*_ 'g-m/s^2'", US),
1011 "0.33333__ g-m/s^2");
1013 // Test padding before a sign
1014 final String formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1015 expect2(new DecimalFormat(formatStr, US), -10, "xxxxxxxxxx(10.0)");
1016 expect2(new DecimalFormat(formatStr, US), -1000, "xxxxxxx(1,000.0)");
1017 expect2(new DecimalFormat(formatStr, US), -1000000, "xxx(1,000,000.0)");
1018 expect2(new DecimalFormat(formatStr, US), -100.37, "xxxxxxxx(100.37)");
1019 expect2(new DecimalFormat(formatStr, US), -10456.37, "xxxxx(10,456.37)");
1020 expect2(new DecimalFormat(formatStr, US), -1120456.37, "xx(1,120,456.37)");
1021 expect2(new DecimalFormat(formatStr, US), -112045600.37, "(112,045,600.37)");
1022 expect2(new DecimalFormat(formatStr, US), -1252045600.37, "(1,252,045,600.37)");
1024 expect2(new DecimalFormat(formatStr, US), 10, "xxxxxxxxxxxx10.0");
1025 expect2(new DecimalFormat(formatStr, US), 1000, "xxxxxxxxx1,000.0");
1026 expect2(new DecimalFormat(formatStr, US), 1000000, "xxxxx1,000,000.0");
1027 expect2(new DecimalFormat(formatStr, US), 100.37, "xxxxxxxxxx100.37");
1028 expect2(new DecimalFormat(formatStr, US), 10456.37, "xxxxxxx10,456.37");
1029 expect2(new DecimalFormat(formatStr, US), 1120456.37, "xxxx1,120,456.37");
1030 expect2(new DecimalFormat(formatStr, US), 112045600.37, "xx112,045,600.37");
1031 expect2(new DecimalFormat(formatStr, US), 10252045600.37, "10,252,045,600.37");
1033 // Test padding between a sign and a number
1034 final String formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1035 expect2(new DecimalFormat(formatStr2, US), -10, "(10.0xxxxxxxxxx)");
1036 expect2(new DecimalFormat(formatStr2, US), -1000, "(1,000.0xxxxxxx)");
1037 expect2(new DecimalFormat(formatStr2, US), -1000000, "(1,000,000.0xxx)");
1038 expect2(new DecimalFormat(formatStr2, US), -100.37, "(100.37xxxxxxxx)");
1039 expect2(new DecimalFormat(formatStr2, US), -10456.37, "(10,456.37xxxxx)");
1040 expect2(new DecimalFormat(formatStr2, US), -1120456.37, "(1,120,456.37xx)");
1041 expect2(new DecimalFormat(formatStr2, US), -112045600.37, "(112,045,600.37)");
1042 expect2(new DecimalFormat(formatStr2, US), -1252045600.37, "(1,252,045,600.37)");
1044 expect2(new DecimalFormat(formatStr2, US), 10, "10.0xxxxxxxxxxxx");
1045 expect2(new DecimalFormat(formatStr2, US), 1000, "1,000.0xxxxxxxxx");
1046 expect2(new DecimalFormat(formatStr2, US), 1000000, "1,000,000.0xxxxx");
1047 expect2(new DecimalFormat(formatStr2, US), 100.37, "100.37xxxxxxxxxx");
1048 expect2(new DecimalFormat(formatStr2, US), 10456.37, "10,456.37xxxxxxx");
1049 expect2(new DecimalFormat(formatStr2, US), 1120456.37, "1,120,456.37xxxx");
1050 expect2(new DecimalFormat(formatStr2, US), 112045600.37, "112,045,600.37xx");
1051 expect2(new DecimalFormat(formatStr2, US), 10252045600.37, "10,252,045,600.37");
1053 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1054 DecimalFormat fmt = new DecimalFormat("#", US);
1055 char padString = 'P';
1056 fmt.setPadCharacter(padString);
1057 expectPad(fmt, "*P##.##", DecimalFormat.PAD_BEFORE_PREFIX, 5, padString);
1058 fmt.setPadCharacter('^');
1059 expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^');
1060 //commented untill implementation is complete
1061 /* fmt.setPadCharacter((UnicodeString)"^^^");
1062 expectPad(fmt, "*^^^#", DecimalFormat.kPadBeforePrefix, 3, (UnicodeString)"^^^");
1064 padString.append((UChar)0x0061);
1065 padString.append((UChar)0x0302);
1066 fmt.setPadCharacter(padString);
1067 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1068 UnicodeString pattern(patternChars);
1069 expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString);
1074 * Upgrade to alphaWorks
1076 public void TestPatterns2() {
1077 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1078 DecimalFormat fmt = new DecimalFormat("#", US);
1080 char hat = 0x005E; /*^*/
1082 expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, hat);
1083 expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, hat);
1084 expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, hat);
1085 expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, hat);
1086 expectPad(fmt, "$*^$#", -1);
1087 expectPad(fmt, "#$*^$", -1);
1088 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX, 12, (char) 0x0078 /*x*/);
1089 expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX, 3, (char) 0x0078 /*x*/);
1090 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX, 10, (char) 0x0061 /*a*/);
1092 fmt.applyPattern("AA#,##0.00ZZ");
1093 fmt.setPadCharacter(hat);
1095 fmt.setFormatWidth(10);
1097 fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX);
1098 expectPat(fmt, "*^AA#,##0.00ZZ");
1100 fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX);
1101 expectPat(fmt, "AA#,##0.00*^ZZ");
1103 fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX);
1104 expectPat(fmt, "AA#,##0.00ZZ*^");
1107 String exp = "AA*^#,##0.00ZZ";
1108 fmt.setFormatWidth(12);
1109 fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX);
1110 expectPat(fmt, exp);
1112 fmt.setFormatWidth(13);
1114 expectPat(fmt, "AA*^##,##0.00ZZ");
1116 fmt.setFormatWidth(14);
1118 expectPat(fmt, "AA*^###,##0.00ZZ");
1120 fmt.setFormatWidth(15);
1122 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1124 fmt.setFormatWidth(16);
1125 // 12 34567890123456
1126 expectPat(fmt, "AA*^#,###,##0.00ZZ");
1129 public void TestRegistration() {
1130 final ULocale SRC_LOC = ULocale.FRANCE;
1131 final ULocale SWAP_LOC = ULocale.US;
1133 class TestFactory extends SimpleNumberFormatFactory {
1134 NumberFormat currencyStyle;
1137 super(SRC_LOC, true);
1138 currencyStyle = NumberFormat.getIntegerInstance(SWAP_LOC);
1141 public NumberFormat createFormat(ULocale loc, int formatType) {
1142 if (formatType == FORMAT_CURRENCY) {
1143 return currencyStyle;
1149 NumberFormat f0 = NumberFormat.getIntegerInstance(SWAP_LOC);
1150 NumberFormat f1 = NumberFormat.getIntegerInstance(SRC_LOC);
1151 NumberFormat f2 = NumberFormat.getCurrencyInstance(SRC_LOC);
1152 Object key = NumberFormat.registerFactory(new TestFactory());
1153 NumberFormat f3 = NumberFormat.getCurrencyInstance(SRC_LOC);
1154 NumberFormat f4 = NumberFormat.getIntegerInstance(SRC_LOC);
1155 NumberFormat.unregister(key); // restore for other tests
1156 NumberFormat f5 = NumberFormat.getCurrencyInstance(SRC_LOC);
1158 float n = 1234.567f;
1159 logln("f0 swap int: " + f0.format(n));
1160 logln("f1 src int: " + f1.format(n));
1161 logln("f2 src cur: " + f2.format(n));
1162 logln("f3 reg cur: " + f3.format(n));
1163 logln("f4 reg int: " + f4.format(n));
1164 logln("f5 unreg cur: " + f5.format(n));
1166 if (!f3.format(n).equals(f0.format(n))) {
1167 errln("registered service did not match");
1169 if (!f4.format(n).equals(f1.format(n))) {
1170 errln("registered service did not inherit");
1172 if (!f5.format(n).equals(f2.format(n))) {
1173 errln("unregistered service did not match original");
1177 public void TestScientific2() {
1179 DecimalFormat fmt = (DecimalFormat)NumberFormat.getCurrencyInstance();
1180 Number num = new Double(12.34);
1181 expect(fmt, num, "$12.34");
1182 fmt.setScientificNotation(true);
1183 expect(fmt, num, "$1.23E1");
1184 fmt.setScientificNotation(false);
1185 expect(fmt, num, "$12.34");
1188 public void TestScientificGrouping() {
1190 DecimalFormat fmt = new DecimalFormat("###.##E0");
1191 expect(fmt, .01234, "12.3E-3");
1192 expect(fmt, .1234, "123E-3");
1193 expect(fmt, 1.234, "1.23E0");
1194 expect(fmt, 12.34, "12.3E0");
1195 expect(fmt, 123.4, "123E0");
1196 expect(fmt, 1234, "1.23E3");
1199 // additional coverage tests
1201 // sigh, can't have static inner classes, why not?
1203 static final class PI extends Number {
1207 private static final long serialVersionUID = -305601227915602172L;
1210 public int intValue() { return (int)Math.PI; }
1211 public long longValue() { return (long)Math.PI; }
1212 public float floatValue() { return (float)Math.PI; }
1213 public double doubleValue() { return (double)Math.PI; }
1214 public byte byteValue() { return (byte)Math.PI; }
1215 public short shortValue() { return (short)Math.PI; }
1217 public static final Number INSTANCE = new PI();
1220 public void TestCoverage() {
1221 NumberFormat fmt = NumberFormat.getNumberInstance(); // default locale
1222 logln(fmt.format(new BigInteger("1234567890987654321234567890987654321", 10)));
1224 fmt = NumberFormat.getScientificInstance(); // default locale
1226 logln(fmt.format(PI.INSTANCE));
1229 logln(fmt.format("12345"));
1230 errln("numberformat of string did not throw exception");
1232 catch (Exception e) {
1233 logln("PASS: numberformat of string failed as expected");
1236 int hash = fmt.hashCode();
1237 logln("hash code " + hash);
1239 logln("compare to string returns: " + fmt.equals(""));
1241 // For ICU 2.6 - alan
1242 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1243 DecimalFormat df = new DecimalFormat("'*&'' '\u00A4' ''&*' #,##0.00", US);
1244 df.setCurrency(Currency.getInstance("INR"));
1245 expect2(df, 1.0, "*&' \u20B9 '&* 1.00");
1246 expect2(df, -2.0, "-*&' \u20B9 '&* 2.00");
1247 df.applyPattern("#,##0.00 '*&'' '\u00A4' ''&*'");
1248 expect2(df, 2.0, "2.00 *&' \u20B9 '&*");
1249 expect2(df, -1.0, "-1.00 *&' \u20B9 '&*");
1251 //#if defined(ECLIPSE)
1254 java.math.BigDecimal r;
1256 r = df.getRoundingIncrement();
1258 errln("FAIL: rounding = " + r + ", expect null");
1261 if (df.isScientificNotation()) {
1262 errln("FAIL: isScientificNotation = true, expect false");
1265 df.applyPattern("0.00000");
1266 df.setScientificNotation(true);
1267 if (!df.isScientificNotation()) {
1268 errln("FAIL: isScientificNotation = false, expect true");
1270 df.setMinimumExponentDigits((byte)2);
1271 if (df.getMinimumExponentDigits() != 2) {
1272 errln("FAIL: getMinimumExponentDigits = " +
1273 df.getMinimumExponentDigits() + ", expect 2");
1275 df.setExponentSignAlwaysShown(true);
1276 if (!df.isExponentSignAlwaysShown()) {
1277 errln("FAIL: isExponentSignAlwaysShown = false, expect true");
1279 df.setSecondaryGroupingSize(0);
1280 if (df.getSecondaryGroupingSize() != 0) {
1281 errln("FAIL: getSecondaryGroupingSize = " +
1282 df.getSecondaryGroupingSize() + ", expect 0");
1284 expect2(df, 3.14159, "3.14159E+00");
1286 // DecimalFormatSymbols#getInstance
1287 DecimalFormatSymbols decsym1 = DecimalFormatSymbols.getInstance();
1288 DecimalFormatSymbols decsym2 = new DecimalFormatSymbols();
1289 if (!decsym1.equals(decsym2)) {
1290 errln("FAIL: DecimalFormatSymbols returned by getInstance()" +
1291 "does not match new DecimalFormatSymbols().");
1293 decsym1 = DecimalFormatSymbols.getInstance(Locale.JAPAN);
1294 decsym2 = DecimalFormatSymbols.getInstance(ULocale.JAPAN);
1295 if (!decsym1.equals(decsym2)) {
1296 errln("FAIL: DecimalFormatSymbols returned by getInstance(Locale.JAPAN)" +
1297 "does not match the one returned by getInstance(ULocale.JAPAN).");
1300 // DecimalFormatSymbols#getAvailableLocales/#getAvailableULocales
1301 Locale[] allLocales = DecimalFormatSymbols.getAvailableLocales();
1302 if (allLocales.length == 0) {
1303 errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1305 logln("PASS: " + allLocales.length +
1306 " available locales returned by DecimalFormatSymbols.getAvailableLocales");
1308 ULocale[] allULocales = DecimalFormatSymbols.getAvailableULocales();
1309 if (allULocales.length == 0) {
1310 errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1312 logln("PASS: " + allULocales.length +
1313 " available locales returned by DecimalFormatSymbols.getAvailableULocales");
1317 public void TestWhiteSpaceParsing() {
1318 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1319 DecimalFormat fmt = new DecimalFormat("a b#0c ", US);
1321 expect(fmt, "a b1234c ", n);
1322 expect(fmt, "a b1234c ", n);
1326 * Test currencies whose display name is a ChoiceFormat.
1328 public void TestComplexCurrency() {
1329 // CLDR No Longer uses complex currency symbols.
1330 // Skipping this test.
1331 // Locale loc = new Locale("kn", "IN", "");
1332 // NumberFormat fmt = NumberFormat.getCurrencyInstance(loc);
1334 // expect2(fmt, 1.0, "Re.\u00a01.00");
1335 // expect(fmt, 1.001, "Re.\u00a01.00"); // tricky
1336 // expect2(fmt, 12345678.0, "Rs.\u00a01,23,45,678.00");
1337 // expect2(fmt, 0.5, "Rs.\u00a00.50");
1338 // expect2(fmt, -1.0, "-Re.\u00a01.00");
1339 // expect2(fmt, -10.0, "-Rs.\u00a010.00");
1342 public void TestCurrencyKeyword() {
1343 ULocale locale = new ULocale("th_TH@currency=QQQ");
1344 NumberFormat format = NumberFormat.getCurrencyInstance(locale);
1345 String result = format.format(12.34f);
1346 if (!"QQQ12.34".equals(result)) {
1347 errln("got unexpected currency: " + result);
1352 * Test alternate numbering systems
1354 public void TestNumberingSystems() {
1356 ULocale loc1 = new ULocale("en_US@numbers=thai");
1357 ULocale loc2 = new ULocale("en_US@numbers=hebr");
1358 ULocale loc3 = new ULocale("en_US@numbers=arabext");
1359 ULocale loc4 = new ULocale("hi_IN@numbers=foobar");
1360 ULocale loc5 = new ULocale("ar_EG"); // ar_EG uses arab numbering system
1361 ULocale loc6 = new ULocale("ar_MA"); // ar_MA users latn numbering system
1362 ULocale loc7 = new ULocale("en_US@numbers=hanidec"); // hanidec is a non-contiguous ns
1364 NumberFormat fmt1 = NumberFormat.getInstance(loc1);
1365 NumberFormat fmt2 = NumberFormat.getInstance(loc2);
1366 NumberFormat fmt3 = NumberFormat.getInstance(loc3);
1367 NumberFormat fmt4 = NumberFormat.getInstance(loc4);
1368 NumberFormat fmt5 = NumberFormat.getInstance(loc5);
1369 NumberFormat fmt6 = NumberFormat.getInstance(loc6);
1370 NumberFormat fmt7 = NumberFormat.getInstance(loc7);
1372 expect2(fmt1,1234.567,"\u0e51,\u0e52\u0e53\u0e54.\u0e55\u0e56\u0e57");
1373 expect3(fmt2,5678.0,"\u05d4\u05f3\u05ea\u05e8\u05e2\u05f4\u05d7");
1374 expect2(fmt3,1234.567,"\u06f1\u066c\u06f2\u06f3\u06f4\u066b\u06f5\u06f6\u06f7");
1375 expect2(fmt4,1234.567,"\u0967,\u0968\u0969\u096a.\u096b\u096c\u096d");
1376 expect2(fmt5,1234.567,"\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666\u0667");
1377 expect2(fmt6,1234.567,"1.234,567");
1378 expect2(fmt7,1234.567, "\u4e00,\u4e8c\u4e09\u56db.\u4e94\u516d\u4e03");
1382 public void Test6816() {
1383 Currency cur1 = Currency.getInstance(new Locale("und", "PH"));
1385 NumberFormat nfmt = NumberFormat.getCurrencyInstance(new Locale("und", "PH"));
1386 DecimalFormatSymbols decsym = ((DecimalFormat)nfmt).getDecimalFormatSymbols();
1387 Currency cur2 = decsym.getCurrency();
1389 if ( !cur1.getCurrencyCode().equals("PHP") || !cur2.getCurrencyCode().equals("PHP")) {
1390 errln("FAIL: Currencies should match PHP: cur1 = "+cur1.getCurrencyCode()+"; cur2 = "+cur2.getCurrencyCode());
1395 public void TestThreadedFormat() {
1397 class FormatTask implements Runnable {
1403 FormatTask(DecimalFormat fmt, int index) {
1405 this.buf = new StringBuffer();
1406 this.inc = (index & 0x1) == 0;
1407 this.num = inc ? 0 : 10000;
1412 while (num < 10000) {
1413 buf.append(fmt.format(num) + "\n");
1418 buf.append(fmt.format(num) + "\n");
1425 return buf.toString();
1429 DecimalFormat fmt = new DecimalFormat("0.####");
1430 FormatTask[] tasks = new FormatTask[8];
1431 for (int i = 0; i < tasks.length; ++i) {
1432 tasks[i] = new FormatTask(fmt, i);
1435 TestUtil.runUntilDone(tasks);
1437 for (int i = 2; i < tasks.length; i++) {
1438 String str1 = tasks[i].result();
1439 String str2 = tasks[i-2].result();
1440 if (!str1.equals(str2)) {
1441 System.out.println("mismatch at " + i);
1442 System.out.println(str1);
1443 System.out.println(str2);
1444 errln("decimal format thread mismatch");
1452 public void TestPerMill() {
1453 DecimalFormat fmt = new DecimalFormat("###.###\u2030");
1454 assertEquals("0.4857 x ###.###\u2030",
1455 "485.7\u2030", fmt.format(0.4857));
1457 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.ENGLISH);
1458 sym.setPerMill('m');
1459 DecimalFormat fmt2 = new DecimalFormat("", sym);
1460 fmt2.applyLocalizedPattern("###.###m");
1461 assertEquals("0.4857 x ###.###m",
1462 "485.7m", fmt2.format(0.4857));
1465 public void TestIllegalPatterns() {
1467 // Prefix with "-:" for illegal patterns
1468 // Prefix with "+:" for legal patterns
1470 // Unquoted special characters in the suffix are illegal
1474 for (int i=0; i<DATA.length; ++i) {
1476 boolean valid = pat.charAt(0) == '+';
1477 pat = pat.substring(2);
1480 // locale doesn't matter here
1481 new DecimalFormat(pat);
1482 } catch (IllegalArgumentException e1) {
1484 } catch (IndexOutOfBoundsException e1) {
1487 String msg = (e==null) ? "success" : e.getMessage();
1488 if ((e==null) == valid) {
1489 logln("Ok: pattern \"" + pat + "\": " + msg);
1491 errln("FAIL: pattern \"" + pat + "\" should have " +
1492 (valid?"succeeded":"failed") + "; got " + msg);
1498 * Parse a CurrencyAmount using the given NumberFormat, with
1499 * the 'delim' character separating the number and the currency.
1501 private static CurrencyAmount parseCurrencyAmount(String str, NumberFormat fmt,
1503 throws ParseException {
1504 int i = str.indexOf(delim);
1505 return new CurrencyAmount(fmt.parse(str.substring(0,i)),
1506 Currency.getInstance(str.substring(i+1)));
1510 * Return an integer representing the next token from this
1511 * iterator. The integer will be an index into the given list, or
1512 * -1 if there are no more tokens, or -2 if the token is not on
1515 private static int keywordIndex(String tok) {
1516 for (int i=0; i<KEYWORDS.length; ++i) {
1517 if (tok.equals(KEYWORDS[i])) {
1524 private static final String KEYWORDS[] = {
1525 /*0*/ "ref=", // <reference pattern to parse numbers>
1526 /*1*/ "loc=", // <locale for formats>
1527 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
1528 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
1529 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
1530 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
1531 /*6*/ "perr:", // <pattern or '-'> <invalid string>
1532 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1533 /*8*/ "fpc:", // <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1534 /*9*/ "strict=", // true or false
1537 public void TestCases() {
1538 String caseFileName = "NumberFormatTestCases.txt";
1539 java.io.InputStream is = NumberFormatTest.class.getResourceAsStream(caseFileName);
1541 ResourceReader reader = new ResourceReader(is, caseFileName, "utf-8");
1542 TokenIterator tokens = new TokenIterator(reader);
1544 Locale loc = new Locale("en", "US", "");
1545 DecimalFormat ref = null, fmt = null;
1546 MeasureFormat mfmt = null;
1547 String pat = null, str = null, mloc = null;
1548 boolean strict = false;
1552 String tok = tokens.next();
1556 String where = "(" + tokens.getLineNumber() + ") ";
1557 int cmd = keywordIndex(tok);
1560 // ref= <reference pattern>
1561 ref = new DecimalFormat(tokens.next(),
1562 new DecimalFormatSymbols(Locale.US));
1563 ref.setParseStrict(strict);
1564 logln("Setting reference pattern to:\t" + ref);
1568 loc = LocaleUtility.getLocaleFromName(tokens.next());
1569 pat = ((DecimalFormat) NumberFormat.getInstance(loc)).toPattern();
1570 logln("Setting locale to:\t" + loc + ", \tand pattern to:\t" + pat);
1576 tok = tokens.next();
1577 if (!tok.equals("-")) {
1581 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc));
1582 fmt.setParseStrict(strict);
1583 } catch (IllegalArgumentException iae) {
1584 errln(where + "Pattern \"" + pat + '"');
1585 iae.printStackTrace();
1586 tokens.next(); // consume remaining tokens
1588 if (cmd == 3) tokens.next();
1593 if (cmd == 2 || cmd == 3 || cmd == 4) {
1594 // f: <pattern or '-'> <number> <exp. string>
1595 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
1596 // rt: <pattern or '-'> <number> <string>
1597 String num = tokens.next();
1598 str = tokens.next();
1599 Number n = (Number) ref.parse(num);
1600 assertEquals(where + '"' + pat + "\".format(" + num + ")",
1601 str, fmt.format(n));
1602 if (cmd == 3) { // fp:
1603 n = (Number) ref.parse(tokens.next());
1605 if (cmd != 2) { // != f:
1606 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1610 // p: <pattern or '-'> <string to parse> <exp. number>
1612 str = tokens.next();
1613 String expstr = tokens.next();
1614 Number parsed = fmt.parse(str);
1615 Number exp = (Number) ref.parse(expstr);
1616 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1619 } catch (ParseException e) {
1620 errln(where + '"' + pat + "\".parse(\"" + str +
1621 "\") threw an exception");
1622 e.printStackTrace();
1626 // perr: <pattern or '-'> <invalid string>
1627 errln("Under construction");
1630 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
1631 String testpat = tokens.next();
1632 String exppat = tokens.next();
1633 boolean err = exppat.equals("err");
1634 if (testpat.equals("-")) {
1636 errln("Invalid command \"pat: - err\" at " + tokens.describePosition());
1641 if (exppat.equals("-")) exppat = testpat;
1643 DecimalFormat f = null;
1644 if (testpat == pat) { // [sic]
1647 f = new DecimalFormat(testpat);
1648 f.setParseStrict(strict);
1651 errln(where + "Invalid pattern \"" + testpat +
1654 assertEquals(where + '"' + testpat + "\".toPattern()",
1655 exppat, f.toPattern());
1657 } catch (IllegalArgumentException iae2) {
1659 logln("Ok: " + where + "Invalid pattern \"" + testpat +
1660 "\" threw an exception");
1662 errln(where + "Valid pattern \"" + testpat +
1663 "\" threw an exception");
1664 iae2.printStackTrace();
1669 tok = tokens.next();
1670 if (!tok.equals("-")) {
1672 ULocale l = new ULocale(mloc);
1674 mfmt = MeasureFormat.getCurrencyFormat(l);
1675 } catch (IllegalArgumentException iae) {
1676 errln(where + "Loc \"" + tok + '"');
1677 iae.printStackTrace();
1678 tokens.next(); // consume remaining tokens
1686 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1687 String currAmt = tokens.next();
1688 str = tokens.next();
1689 CurrencyAmount target = parseCurrencyAmount(currAmt, ref, '/');
1690 String formatResult = mfmt.format(target);
1691 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
1693 target = parseCurrencyAmount(tokens.next(), ref, '/');
1694 CurrencyAmount parseResult = (CurrencyAmount) mfmt.parseObject(str);
1695 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
1696 target, parseResult);
1697 } catch (ParseException e) {
1698 errln(where + '"' + pat + "\".parse(\"" + str +
1699 "\") threw an exception");
1700 e.printStackTrace();
1703 case 9: // strict= true or false
1704 strict = "true".equalsIgnoreCase(tokens.next());
1705 logln("Setting strict to:\t" + strict);
1708 errln("Unknown command \"" + tok + "\" at " + tokens.describePosition());
1712 } catch (java.io.IOException e) {
1713 throw new RuntimeException(e);
1717 public void TestRounding() {
1718 DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
1719 if (false) { // for debugging specific value
1720 nf.setRoundingMode(BigDecimal.ROUND_HALF_UP);
1721 checkRounding(nf, new BigDecimal("300.0300000000"), 0, new BigDecimal("0.020000000"));
1724 int[] roundingIncrements = {1, 2, 5, 20, 50, 100};
1725 int[] testValues = {0, 300};
1726 for (int j = 0; j < testValues.length; ++j) {
1727 for (int mode = BigDecimal.ROUND_UP; mode < BigDecimal.ROUND_HALF_EVEN; ++mode) {
1728 nf.setRoundingMode(mode);
1729 for (int increment = 0; increment < roundingIncrements.length; ++increment) {
1730 BigDecimal base = new BigDecimal(testValues[j]);
1731 BigDecimal rInc = new BigDecimal(roundingIncrements[increment]);
1732 checkRounding(nf, base, 20, rInc);
1733 rInc = new BigDecimal("1.000000000").divide(rInc);
1734 checkRounding(nf, base, 20, rInc);
1740 public void TestBigDecimalRounding() {
1741 String figure = "50.000000004";
1742 Double dbl = new Double(figure);
1743 BigDecimal dec = new BigDecimal(figure);
1745 DecimalFormat f = (DecimalFormat) NumberFormat.getInstance();
1746 f.applyPattern("00.00######");
1748 assertEquals("double format", "50.00", f.format(dbl));
1749 assertEquals("bigdec format", "50.00", f.format(dec));
1751 int maxFracDigits = f.getMaximumFractionDigits();
1752 BigDecimal roundingIncrement = new BigDecimal("1").movePointLeft(maxFracDigits);
1754 f.setRoundingIncrement(roundingIncrement);
1755 f.setRoundingMode(BigDecimal.ROUND_DOWN);
1756 assertEquals("Rounding down", f.format(dbl), f.format(dec));
1758 f.setRoundingIncrement(roundingIncrement);
1759 f.setRoundingMode(BigDecimal.ROUND_HALF_UP);
1760 assertEquals("Rounding half up", f.format(dbl), f.format(dec));
1763 void checkRounding(DecimalFormat nf, BigDecimal base, int iterations, BigDecimal increment) {
1764 nf.setRoundingIncrement(increment.toBigDecimal());
1765 BigDecimal lastParsed = new BigDecimal(Integer.MIN_VALUE); // used to make sure that rounding is monotonic
1766 for (int i = -iterations; i <= iterations; ++i) {
1767 BigDecimal iValue = base.add(increment.multiply(new BigDecimal(i)).movePointLeft(1));
1768 BigDecimal smallIncrement = new BigDecimal("0.00000001");
1769 if (iValue.signum() != 0) {
1770 smallIncrement.multiply(iValue); // scale unless zero
1772 // we not only test the value, but some values in a small range around it.
1773 lastParsed = checkRound(nf, iValue.subtract(smallIncrement), lastParsed);
1774 lastParsed = checkRound(nf, iValue, lastParsed);
1775 lastParsed = checkRound(nf, iValue.add(smallIncrement), lastParsed);
1779 private BigDecimal checkRound(DecimalFormat nf, BigDecimal iValue, BigDecimal lastParsed) {
1780 String formatedBigDecimal = nf.format(iValue);
1781 String formattedDouble = nf.format(iValue.doubleValue());
1782 if (!equalButForTrailingZeros(formatedBigDecimal, formattedDouble)) {
1784 errln("Failure at: " + iValue + " (" + iValue.doubleValue() + ")"
1785 + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1786 + ",\tRounding-increment: " + nf.getRoundingIncrement()
1787 + ",\tdouble: " + formattedDouble
1788 + ",\tBigDecimal: " + formatedBigDecimal);
1791 logln("Value: " + iValue
1792 + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1793 + ",\tRounding-increment: " + nf.getRoundingIncrement()
1794 + ",\tdouble: " + formattedDouble
1795 + ",\tBigDecimal: " + formatedBigDecimal);
1798 // Number should have compareTo(...)
1799 BigDecimal parsed = toBigDecimal(nf.parse(formatedBigDecimal));
1800 if (lastParsed.compareTo(parsed) > 0) {
1801 errln("Rounding wrong direction!: " + lastParsed + " > " + parsed);
1803 lastParsed = parsed;
1804 } catch (ParseException e) {
1805 errln("Parse Failure with: " + formatedBigDecimal);
1810 static BigDecimal toBigDecimal(Number number) {
1811 return number instanceof BigDecimal ? (BigDecimal) number
1812 : number instanceof BigInteger ? new BigDecimal((BigInteger)number)
1813 : number instanceof java.math.BigDecimal ? new BigDecimal((java.math.BigDecimal)number)
1814 : number instanceof Double ? new BigDecimal(number.doubleValue())
1815 : number instanceof Float ? new BigDecimal(number.floatValue())
1816 : new BigDecimal(number.longValue());
1819 static String[] roundingModeNames = {
1820 "ROUND_UP", "ROUND_DOWN", "ROUND_CEILING", "ROUND_FLOOR",
1821 "ROUND_HALF_UP", "ROUND_HALF_DOWN", "ROUND_HALF_EVEN",
1825 private static boolean equalButForTrailingZeros(String formatted1, String formatted2) {
1826 if (formatted1.length() == formatted2.length()) return formatted1.equals(formatted2);
1827 return stripFinalZeros(formatted1).equals(stripFinalZeros(formatted2));
1830 private static String stripFinalZeros(String formatted) {
1831 int len1 = formatted.length();
1833 while (len1 > 0 && ((ch = formatted.charAt(len1-1)) == '0' || ch == '.')) --len1;
1834 if (len1==1 && ((ch = formatted.charAt(len1-1)) == '-')) --len1;
1835 return formatted.substring(0,len1);
1838 //------------------------------------------------------------------
1840 //------------------------------------------------------------------
1842 // Format-Parse test
1843 public void expect2(NumberFormat fmt, Number n, String exp) {
1844 // Don't round-trip format test, since we explicitly do it
1845 expect(fmt, n, exp, false);
1846 expect(fmt, exp, n);
1848 // Format-Parse test
1849 public void expect3(NumberFormat fmt, Number n, String exp) {
1850 // Don't round-trip format test, since we explicitly do it
1851 expect_rbnf(fmt, n, exp, false);
1852 expect_rbnf(fmt, exp, n);
1855 // Format-Parse test (convenience)
1856 public void expect2(NumberFormat fmt, double n, String exp) {
1857 expect2(fmt, new Double(n), exp);
1859 // Format-Parse test (convenience)
1860 public void expect3(NumberFormat fmt, double n, String exp) {
1861 expect3(fmt, new Double(n), exp);
1864 // Format-Parse test (convenience)
1865 public void expect2(NumberFormat fmt, long n, String exp) {
1866 expect2(fmt, new Long(n), exp);
1868 // Format-Parse test (convenience)
1869 public void expect3(NumberFormat fmt, long n, String exp) {
1870 expect3(fmt, new Long(n), exp);
1874 public void expect(NumberFormat fmt, Number n, String exp, boolean rt) {
1875 StringBuffer saw = new StringBuffer();
1876 FieldPosition pos = new FieldPosition(0);
1877 fmt.format(n, saw, pos);
1878 String pat = ((DecimalFormat)fmt).toPattern();
1879 if (saw.toString().equals(exp)) {
1880 logln("Ok " + n + " x " +
1883 // We should be able to round-trip the formatted string =>
1884 // number => string (but not the other way around: number
1885 // => string => number2, might have number2 != number):
1888 Number n2 = fmt.parse(exp);
1889 StringBuffer saw2 = new StringBuffer();
1890 fmt.format(n2, saw2, pos);
1891 if (!saw2.toString().equals(exp)) {
1892 errln("FAIL \"" + exp + "\" => " + n2 +
1893 " => \"" + saw2 + '"');
1895 } catch (ParseException e) {
1896 errln(e.getMessage());
1901 errln("FAIL " + n + " x " +
1903 saw + "\", expected \"" + exp + "\"");
1907 public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) {
1908 StringBuffer saw = new StringBuffer();
1909 FieldPosition pos = new FieldPosition(0);
1910 fmt.format(n, saw, pos);
1911 if (saw.toString().equals(exp)) {
1912 logln("Ok " + n + " = \"" +
1914 // We should be able to round-trip the formatted string =>
1915 // number => string (but not the other way around: number
1916 // => string => number2, might have number2 != number):
1919 Number n2 = fmt.parse(exp);
1920 StringBuffer saw2 = new StringBuffer();
1921 fmt.format(n2, saw2, pos);
1922 if (!saw2.toString().equals(exp)) {
1923 errln("FAIL \"" + exp + "\" => " + n2 +
1924 " => \"" + saw2 + '"');
1926 } catch (ParseException e) {
1927 errln(e.getMessage());
1932 errln("FAIL " + n + " = \"" +
1933 saw + "\", expected \"" + exp + "\"");
1937 // Format test (convenience)
1938 public void expect(NumberFormat fmt, Number n, String exp) {
1939 expect(fmt, n, exp, true);
1942 // Format test (convenience)
1943 public void expect(NumberFormat fmt, double n, String exp) {
1944 expect(fmt, new Double(n), exp);
1947 // Format test (convenience)
1948 public void expect(NumberFormat fmt, long n, String exp) {
1949 expect(fmt, new Long(n), exp);
1953 public void expect(NumberFormat fmt, String str, Number n) {
1956 num = (Number) fmt.parse(str);
1957 } catch (ParseException e) {
1958 errln(e.getMessage());
1961 String pat = ((DecimalFormat)fmt).toPattern();
1962 // A little tricky here -- make sure Double(12345.0) and
1963 // Long(12345) match.
1964 if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1965 logln("Ok \"" + str + "\" x " +
1969 errln("FAIL \"" + str + "\" x " +
1971 num + ", expected " + n);
1976 public void expect_rbnf(NumberFormat fmt, String str, Number n) {
1979 num = (Number) fmt.parse(str);
1980 } catch (ParseException e) {
1981 errln(e.getMessage());
1984 // A little tricky here -- make sure Double(12345.0) and
1985 // Long(12345) match.
1986 if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1987 logln("Ok \"" + str + " = " +
1990 errln("FAIL \"" + str + " = " +
1991 num + ", expected " + n);
1995 // Parse test (convenience)
1996 public void expect(NumberFormat fmt, String str, double n) {
1997 expect(fmt, str, new Double(n));
2000 // Parse test (convenience)
2001 public void expect(NumberFormat fmt, String str, long n) {
2002 expect(fmt, str, new Long(n));
2005 private void expectCurrency(NumberFormat nf, Currency curr,
2006 double value, String string) {
2007 DecimalFormat fmt = (DecimalFormat) nf;
2009 fmt.setCurrency(curr);
2011 String s = fmt.format(value).replace('\u00A0', ' ');
2013 if (s.equals(string)) {
2014 logln("Ok: " + value + " x " + curr + " => " + s);
2016 errln("FAIL: " + value + " x " + curr + " => " + s +
2017 ", expected " + string);
2021 public void expectPad(DecimalFormat fmt, String pat, int pos) {
2022 expectPad(fmt, pat, pos, 0, (char)0);
2025 public void expectPad(DecimalFormat fmt, final String pat, int pos, int width, final char pad) {
2026 int apos = 0, awidth = 0;
2029 fmt.applyPattern(pat);
2030 apos = fmt.getPadPosition();
2031 awidth = fmt.getFormatWidth();
2032 apadStr = fmt.getPadCharacter();
2033 } catch (Exception e) {
2039 if (apos == pos && awidth == width && apadStr == pad) {
2040 logln("Ok \"" + pat + "\" pos="
2041 + apos + ((pos == -1) ? "" : " width=" + awidth + " pad=" + apadStr));
2043 errln("FAIL \"" + pat + "\" pos=" + apos + " width="
2044 + awidth + " pad=" + apadStr + ", expected "
2045 + pos + " " + width + " " + pad);
2049 public void expectPat(DecimalFormat fmt, final String exp) {
2050 String pat = fmt.toPattern();
2051 if (pat.equals(exp)) {
2052 logln("Ok \"" + pat + "\"");
2054 errln("FAIL \"" + pat + "\", expected \"" + exp + "\"");
2058 public void TestJB3832(){
2059 ULocale locale = new ULocale("pt_PT@currency=PTE");
2060 NumberFormat format = NumberFormat.getCurrencyInstance(locale);
2061 Currency curr = Currency.getInstance(locale);
2062 logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
2063 CurrencyAmount cAmt = new CurrencyAmount(1150.50, curr);
2064 logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
2065 String str = format.format(cAmt);
2066 String expected = "1,150$50\u00a0Esc.";
2067 if(!expected.equals(str)){
2068 errln("Did not get the expected output Expected: "+expected+" Got: "+ str);
2072 public void TestStrictParse() {
2074 "0", // single zero before end of text is not leading
2075 "0 ", // single zero at end of number is not leading
2076 "0.", // single zero before period (or decimal, it's ambiguous) is not leading
2077 "0,", // single zero before comma (not group separator) is not leading
2078 "0.0", // single zero before decimal followed by digit is not leading
2079 "0. ", // same as above before period (or decimal) is not leading
2080 "0.100,5", // comma stops parse of decimal (no grouping)
2081 ".00", // leading decimal is ok, even with zeros
2082 "1234567", // group separators are not required
2083 "12345, ", // comma not followed by digit is not a group separator, but end of number
2084 "1,234, ", // if group separator is present, group sizes must be appropriate
2085 "1,234,567", // ...secondary too
2086 "0E", // an exponent not followed by zero or digits is not an exponent
2087 "00", // leading zero before zero - used to be error - see ticket #7913
2088 "012", // leading zero before digit - used to be error - see ticket #7913
2089 "0,456", // leading zero before group separator - used to be error - see ticket #7913
2092 "1,2", // wrong number of digits after group separator
2093 ",0", // leading group separator before zero
2094 ",1", // leading group separator before digit
2095 ",.02", // leading group separator before decimal
2096 "1,.02", // group separator before decimal
2097 "1,,200", // multiple group separators
2098 "1,45", // wrong number of digits in primary group
2099 "1,45 that", // wrong number of digits in primary group
2100 "1,45.34", // wrong number of digits in primary group
2101 "1234,567", // wrong number of digits in secondary group
2102 "12,34,567", // wrong number of digits in secondary group
2103 "1,23,456,7890", // wrong number of digits in primary and secondary groups
2106 DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
2107 runStrictParseBatch(nf, pass, fail);
2109 String[] scientificPass = {
2110 "0E2", // single zero before exponent is ok
2111 "1234E2", // any number of digits before exponent is ok
2112 "1,234E", // an exponent string not followed by zero or digits is not an exponent
2113 "00E2", // leading zeroes now allowed in strict mode - see ticket #
2115 String[] scientificFail = {
2116 "1,234E2", // group separators with exponent fail
2119 nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
2120 runStrictParseBatch(nf, scientificPass, scientificFail);
2122 String[] mixedPass = {
2128 String[] mixedFail = {
2135 nf = new DecimalFormat("#,##,##0.#");
2136 runStrictParseBatch(nf, mixedPass, mixedFail);
2139 void runStrictParseBatch(DecimalFormat nf, String[] pass, String[] fail) {
2140 nf.setParseStrict(false);
2141 runStrictParseTests("should pass", nf, pass, true);
2142 runStrictParseTests("should also pass", nf, fail, true);
2143 nf.setParseStrict(true);
2144 runStrictParseTests("should still pass", nf, pass, true);
2145 runStrictParseTests("should fail", nf, fail, false);
2148 void runStrictParseTests(String msg, DecimalFormat nf, String[] tests, boolean pass) {
2150 logln("pattern: '" + nf.toPattern() + "'");
2152 for (int i = 0; i < tests.length; ++i) {
2153 String str = tests[i];
2154 ParsePosition pp = new ParsePosition(0);
2155 Number n = nf.parse(str, pp);
2156 String formatted = n != null ? nf.format(n) : "null";
2157 String err = pp.getErrorIndex() == -1 ? "" : "(error at " + pp.getErrorIndex() + ")";
2158 if ((err.length() == 0) != pass) {
2159 errln("'" + str + "' parsed '" +
2160 str.substring(0, pp.getIndex()) +
2161 "' returned " + n + " formats to '" +
2162 formatted + "' " + err);
2164 if (err.length() > 0) {
2165 err = "got expected " + err;
2167 logln("'" + str + "' parsed '" +
2168 str.substring(0, pp.getIndex()) +
2169 "' returned " + n + " formats to '" +
2170 formatted + "' " + err);
2174 public void TestJB5251(){
2175 //save default locale
2176 ULocale defaultLocale = ULocale.getDefault();
2177 ULocale.setDefault(new ULocale("qr_QR"));
2179 NumberFormat.getInstance();
2181 catch (Exception e) {
2182 errln("Numberformat threw exception for non-existent locale. It should use the default.");
2184 //reset default locale
2185 ULocale.setDefault(defaultLocale);
2188 public void TestParseReturnType() {
2189 String[] defaultNonBigDecimals = {
2193 "12345678901234567890" // BigInteger
2196 String[] doubles = {
2199 "\u221E" // Infinity
2202 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2203 DecimalFormat nf = new DecimalFormat("#.#", sym);
2205 if (nf.isParseBigDecimal()) {
2206 errln("FAIL: isParseDecimal() must return false by default");
2209 // isParseBigDecimal() is false
2210 for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2212 Number n = nf.parse(defaultNonBigDecimals[i]);
2213 if (n instanceof BigDecimal) {
2214 errln("FAIL: parse returns BigDecimal instance");
2216 } catch (ParseException e) {
2217 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2220 // parse results for doubls must be always Double
2221 for (int i = 0; i < doubles.length; i++) {
2223 Number n = nf.parse(doubles[i]);
2224 if (!(n instanceof Double)) {
2225 errln("FAIL: parse does not return Double instance");
2227 } catch (ParseException e) {
2228 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2232 // force this DecimalFormat to return BigDecimal
2233 nf.setParseBigDecimal(true);
2234 if (!nf.isParseBigDecimal()) {
2235 errln("FAIL: isParseBigDecimal() must return true");
2238 // isParseBigDecimal() is true
2239 for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2241 Number n = nf.parse(defaultNonBigDecimals[i]);
2242 if (!(n instanceof BigDecimal)) {
2243 errln("FAIL: parse does not return BigDecimal instance");
2245 } catch (ParseException e) {
2246 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2249 // parse results for doubls must be always Double
2250 for (int i = 0; i < doubles.length; i++) {
2252 Number n = nf.parse(doubles[i]);
2253 if (!(n instanceof Double)) {
2254 errln("FAIL: parse does not return Double instance");
2256 } catch (ParseException e) {
2257 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2262 public void TestNonpositiveMultiplier() {
2263 DecimalFormat df = new DecimalFormat("0");
2265 // test zero multiplier
2268 df.setMultiplier(0);
2271 errln("DecimalFormat.setMultiplier(0) did not throw an IllegalArgumentException");
2272 } catch (IllegalArgumentException ex) {
2276 // test negative multiplier
2279 df.setMultiplier(-1);
2281 if (df.getMultiplier() != -1) {
2282 errln("DecimalFormat.setMultiplier(-1) did not change the multiplier to -1");
2287 } catch (IllegalArgumentException ex) {
2289 errln("DecimalFormat.setMultiplier(-1) threw an IllegalArgumentException");
2293 expect(df, "1122.123", -1122.123);
2294 expect(df, "-1122.123", 1122.123);
2295 expect(df, "1.2", -1.2);
2296 expect(df, "-1.2", 1.2);
2298 expect2(df, Long.MAX_VALUE, BigInteger.valueOf(Long.MAX_VALUE).negate().toString());
2299 expect2(df, Long.MIN_VALUE, BigInteger.valueOf(Long.MIN_VALUE).negate().toString());
2300 expect2(df, Long.MAX_VALUE / 2, BigInteger.valueOf(Long.MAX_VALUE / 2).negate().toString());
2301 expect2(df, Long.MIN_VALUE / 2, BigInteger.valueOf(Long.MIN_VALUE / 2).negate().toString());
2303 expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2304 expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2306 expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2307 expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2310 public void TestJB5358() {
2311 int numThreads = 10;
2312 String numstr = "12345";
2313 double expected = 12345;
2314 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2315 DecimalFormat fmt = new DecimalFormat("#.#", sym);
2316 ArrayList errors = new ArrayList();
2318 ParseThreadJB5358[] threads = new ParseThreadJB5358[numThreads];
2319 for (int i = 0; i < numThreads; i++) {
2320 threads[i] = new ParseThreadJB5358((DecimalFormat)fmt.clone(), numstr, expected, errors);
2323 for (int i = 0; i < numThreads; i++) {
2326 } catch (InterruptedException ie) {
2327 ie.printStackTrace();
2330 if (errors.size() != 0) {
2331 StringBuffer errBuf = new StringBuffer();
2332 for (int i = 0; i < errors.size(); i++) {
2333 errBuf.append((String)errors.get(i));
2334 errBuf.append("\n");
2336 errln("FAIL: " + errBuf);
2340 static private class ParseThreadJB5358 extends Thread {
2341 private DecimalFormat decfmt;
2342 private String numstr;
2343 private double expect;
2344 private ArrayList errors;
2346 public ParseThreadJB5358(DecimalFormat decfmt, String numstr, double expect, ArrayList errors) {
2347 this.decfmt = decfmt;
2348 this.numstr = numstr;
2349 this.expect = expect;
2350 this.errors = errors;
2354 for (int i = 0; i < 10000; i++) {
2356 Number n = decfmt.parse(numstr);
2357 if (n.doubleValue() != expect) {
2358 synchronized(errors) {
2359 errors.add(new String("Bad parse result - expected:" + expect + " actual:" + n.doubleValue()));
2362 } catch (Throwable t) {
2363 synchronized(errors) {
2364 errors.add(new String(t.getClass().getName() + " - " + t.getMessage()));
2371 public void TestSetCurrency() {
2372 DecimalFormatSymbols decf1 = DecimalFormatSymbols.getInstance(ULocale.US);
2373 DecimalFormatSymbols decf2 = DecimalFormatSymbols.getInstance(ULocale.US);
2374 decf2.setCurrencySymbol("UKD");
2375 DecimalFormat format1 = new DecimalFormat("000.000", decf1);
2376 DecimalFormat format2 = new DecimalFormat("000.000", decf2);
2377 Currency euro = Currency.getInstance("EUR");
2378 format1.setCurrency(euro);
2379 format2.setCurrency(euro);
2380 assertEquals("Reset with currency symbol", format1, format2);
2384 * Testing the method public StringBuffer format(Object number, ...)
2386 public void TestFormat() {
2387 NumberFormat nf = NumberFormat.getInstance();
2388 StringBuffer sb = new StringBuffer("dummy");
2389 FieldPosition fp = new FieldPosition(0);
2391 // Tests when "if (number instanceof Long)" is true
2393 nf.format((Object)new Long("0"), sb, fp);
2394 } catch (Exception e) {
2395 errln("NumberFormat.format(Object number, ...) was not suppose to "
2396 + "return an exception for a Long object. Error: " + e);
2399 // Tests when "else if (number instanceof BigInteger)" is true
2401 nf.format((Object)new BigInteger("0"), sb, fp);
2402 } catch (Exception e) {
2403 errln("NumberFormat.format(Object number, ...) was not suppose to "
2404 + "return an exception for a BigInteger object. Error: " + e);
2407 // Tests when "else if (number instanceof java.math.BigDecimal)" is true
2409 nf.format((Object)new java.math.BigDecimal("0"), sb, fp);
2410 } catch (Exception e) {
2411 errln("NumberFormat.format(Object number, ...) was not suppose to "
2412 + "return an exception for a java.math.BigDecimal object. Error: " + e);
2415 // Tests when "else if (number instanceof com.ibm.icu.math.BigDecimal)" is true
2417 nf.format((Object)new com.ibm.icu.math.BigDecimal("0"), sb, fp);
2418 } catch (Exception e) {
2419 errln("NumberFormat.format(Object number, ...) was not suppose to "
2420 + "return an exception for a com.ibm.icu.math.BigDecimal object. Error: " + e);
2423 // Tests when "else if (number instanceof CurrencyAmount)" is true
2425 CurrencyAmount ca = new CurrencyAmount(0.0, Currency.getInstance(new ULocale("en_US")));
2426 nf.format((Object)ca, sb, fp);
2427 } catch (Exception e) {
2428 errln("NumberFormat.format(Object number, ...) was not suppose to "
2429 + "return an exception for a CurrencyAmount object. Error: " + e);
2432 // Tests when "else if (number instanceof Number)" is true
2434 nf.format((Object)(Number) 0.0, sb, fp);
2435 } catch (Exception e) {
2436 errln("NumberFormat.format(Object number, ...) was not suppose to "
2437 + "to return an exception for a Number object. Error: " + e);
2440 // Tests when "else" is true
2442 nf.format(new Object(), sb, fp);
2443 errln("NumberFormat.format(Object number, ...) was suppose to "
2444 + "return an exception for an invalid object.");
2445 } catch (Exception e) {
2449 nf.format(new String("dummy"), sb, fp);
2450 errln("NumberFormat.format(Object number, ...) was suppose to "
2451 + "return an exception for an invalid object.");
2452 } catch (Exception e) {
2457 * Tests the method public final static NumberFormat getInstance(int style) public static NumberFormat
2458 * getInstance(Locale inLocale, int style) public static NumberFormat getInstance(ULocale desiredLocale, int choice)
2460 public void TestGetInstance() {
2461 // Tests "public final static NumberFormat getInstance(int style)"
2463 int[] invalid_cases = { NumberFormat.NUMBERSTYLE - 1, NumberFormat.NUMBERSTYLE - 2,
2464 NumberFormat.PLURALCURRENCYSTYLE + 1, NumberFormat.PLURALCURRENCYSTYLE + 2 };
2466 for (int i = NumberFormat.NUMBERSTYLE; i < NumberFormat.PLURALCURRENCYSTYLE; i++) {
2468 NumberFormat.getInstance(i);
2469 } catch (Exception e) {
2470 errln("NumberFormat.getInstance(int style) was not suppose to "
2471 + "return an exception for passing value of " + i);
2475 for (int i = 0; i < invalid_cases.length; i++) {
2477 NumberFormat.getInstance(invalid_cases[i]);
2478 errln("NumberFormat.getInstance(int style) was suppose to "
2479 + "return an exception for passing value of " + invalid_cases[i]);
2480 } catch (Exception e) {
2484 // Tests "public static NumberFormat getInstance(Locale inLocale, int style)"
2485 String[] localeCases = { "en_US", "fr_FR", "de_DE", "jp_JP" };
2487 for (int i = NumberFormat.NUMBERSTYLE; i < NumberFormat.PLURALCURRENCYSTYLE; i++) {
2488 for (int j = 0; j < localeCases.length; j++) {
2490 NumberFormat.getInstance(new Locale(localeCases[j]), i);
2491 } catch (Exception e) {
2492 errln("NumberFormat.getInstance(Locale inLocale, int style) was not suppose to "
2493 + "return an exception for passing value of " + localeCases[j] + ", " + i);
2498 // Tests "public static NumberFormat getInstance(ULocale desiredLocale, int choice)"
2499 // Tests when "if (choice < NUMBERSTYLE || choice > PLURALCURRENCYSTYLE)" is true
2500 for (int i = 0; i < invalid_cases.length; i++) {
2502 NumberFormat.getInstance((ULocale) null, invalid_cases[i]);
2503 errln("NumberFormat.getInstance(ULocale inLocale, int choice) was not suppose to "
2504 + "return an exception for passing value of " + invalid_cases[i]);
2505 } catch (Exception e) {
2511 * Tests the class public static abstract class NumberFormatFactory
2513 public void TestNumberFormatFactory() {
2515 * The following class allows the method public NumberFormat createFormat(Locale loc, int formatType) to be
2518 class TestFactory extends NumberFormatFactory {
2519 public Set<String> getSupportedLocaleNames() {
2523 public NumberFormat createFormat(ULocale loc, int formatType) {
2529 * The following class allows the method public NumberFormat createFormat(ULocale loc, int formatType) to be
2532 class TestFactory1 extends NumberFormatFactory {
2533 public Set<String> getSupportedLocaleNames() {
2537 public NumberFormat createFormat(Locale loc, int formatType) {
2542 TestFactory tf = new TestFactory();
2543 TestFactory1 tf1 = new TestFactory1();
2546 * Tests the method public boolean visible()
2548 if (tf.visible() != true) {
2549 errln("NumberFormatFactor.visible() was suppose to return true.");
2553 * Tests the method public NumberFormat createFormat(Locale loc, int formatType)
2555 if (tf.createFormat(new Locale(""), 0) != null) {
2556 errln("NumberFormatFactor.createFormat(Locale loc, int formatType) " + "was suppose to return null");
2560 * Tests the method public NumberFormat createFormat(ULocale loc, int formatType)
2562 if (tf1.createFormat(new ULocale(""), 0) != null) {
2563 errln("NumberFormatFactor.createFormat(ULocale loc, int formatType) " + "was suppose to return null");
2568 * Tests the class public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory
2570 public void TestSimpleNumberFormatFactory() {
2571 class TestSimpleNumberFormatFactory extends SimpleNumberFormatFactory {
2573 * Tests the method public SimpleNumberFormatFactory(Locale locale)
2575 TestSimpleNumberFormatFactory() {
2576 super(new Locale(""));
2579 @SuppressWarnings("unused")
2580 TestSimpleNumberFormatFactory tsnff = new TestSimpleNumberFormatFactory();
2584 * Tests the method public static ULocale[] getAvailableLocales()
2586 @SuppressWarnings("static-access")
2587 public void TestGetAvailableLocales() {
2588 // Tests when "if (shim == null)" is true
2589 @SuppressWarnings("serial")
2590 class TestGetAvailableLocales extends NumberFormat {
2591 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
2595 public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
2599 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
2603 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2607 public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2611 public Number parse(String text, ParsePosition parsePosition) {
2617 TestGetAvailableLocales test = new TestGetAvailableLocales();
2618 test.getAvailableLocales();
2619 } catch (Exception e) {
2620 errln("NumberFormat.getAvailableLocales() was not suppose to "
2621 + "return an exception when getting getting available locales.");
2626 * Tests the method public void setMinimumIntegerDigits(int newValue)
2628 public void TestSetMinimumIntegerDigits() {
2629 NumberFormat nf = NumberFormat.getInstance();
2630 // For valid array, it is displayed as {min value, max value}
2631 // Tests when "if (minimumIntegerDigits > maximumIntegerDigits)" is true
2632 int[][] cases = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 2, 0 }, { 2, 1 }, { 10, 0 } };
2633 int[] expectedMax = { 0, 1, 1, 2, 2, 10 };
2634 if (cases.length != expectedMax.length) {
2635 errln("Can't continue test case method TestSetMinimumIntegerDigits "
2636 + "since the test case arrays are unequal.");
2638 for (int i = 0; i < cases.length; i++) {
2639 nf.setMaximumIntegerDigits(cases[i][1]);
2640 nf.setMinimumIntegerDigits(cases[i][0]);
2641 if (nf.getMaximumIntegerDigits() != expectedMax[i]) {
2642 errln("NumberFormat.setMinimumIntegerDigits(int newValue "
2643 + "did not return an expected result for parameter " + cases[i][1] + " and " + cases[i][0]
2644 + " and expected " + expectedMax[i] + " but got " + nf.getMaximumIntegerDigits());
2651 * Tests the method protected Currency getEffectiveCurrency()
2653 public void TestGetEffectiveCurrency() {
2654 // TODO: Tests the method
2658 * Tests the method public int getRoundingMode() public void setRoundingMode(int roundingMode)
2660 public void TestRoundingMode() {
2661 @SuppressWarnings("serial")
2662 class TestRoundingMode extends NumberFormat {
2663 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
2667 public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
2671 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
2675 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2679 public StringBuffer format(BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
2683 public Number parse(String text, ParsePosition parsePosition) {
2687 TestRoundingMode tgrm = new TestRoundingMode();
2689 // Tests the function 'public void setRoundingMode(int roundingMode)'
2691 tgrm.setRoundingMode(0);
2692 errln("NumberFormat.setRoundingMode(int) was suppose to return an exception");
2693 } catch (Exception e) {
2696 // Tests the function 'public int getRoundingMode()'
2698 tgrm.getRoundingMode();
2699 errln("NumberFormat.getRoundingMode() was suppose to return an exception");
2700 } catch (Exception e) {
2705 * Testing lenient decimal/grouping separator parsing
2707 public void TestLenientSymbolParsing() {
2708 DecimalFormat fmt = new DecimalFormat();
2709 DecimalFormatSymbols sym = new DecimalFormatSymbols();
2711 expect(fmt, "12\u300234", 12.34);
2713 // Ticket#7345 - case 1
2714 // Even strict parsing, the decimal separator set in the symbols
2715 // should be successfully parsed.
2717 sym.setDecimalSeparator('\u3002');
2720 fmt.setDecimalFormatSymbols(sym);
2722 // strict - failed before the fix for #7345
2723 fmt.setParseStrict(true);
2724 expect(fmt, "23\u300245", 23.45);
2725 fmt.setParseStrict(false);
2728 // Ticket#7345 - case 2
2729 // Decimal separator variants other than DecimalFormatSymbols.decimalSeparator
2730 // should not hide the grouping separator DecimalFormatSymbols.groupingSeparator.
2731 sym.setDecimalSeparator('.');
2732 sym.setGroupingSeparator(',');
2733 fmt.setDecimalFormatSymbols(sym);
2735 expect(fmt, "1,234.56", 1234.56);
2737 sym.setGroupingSeparator('\uFF61');
2738 fmt.setDecimalFormatSymbols(sym);
2740 expect(fmt, "2\uFF61345.67", 2345.67);
2744 // Lenient separator parsing is enabled by default.
2745 // A space character below is interpreted as a
2746 // group separator, even ',' is used as grouping
2747 // separator in the symbols.
2748 sym.setGroupingSeparator(',');
2749 fmt.setDecimalFormatSymbols(sym);
2751 expect(fmt, "12 345", 12345);
2753 // When the property SkipExtendedSeparatorParsing is true,
2754 // DecimalFormat does not use the extended equivalent separator
2755 // data and only uses the one in DecimalFormatSymbols.
2756 System.setProperty("com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "true");
2758 expect(fmt, "23 456", 23);
2760 // Set the configuration back to the default
2761 System.setProperty("com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false");
2765 * Testing currency driven max/min fraction digits problem
2766 * reported by ticket#7282
2768 public void TestCurrencyFractionDigits() {
2769 double value = 99.12345;
2771 // Create currency instance
2772 NumberFormat cfmt = NumberFormat.getCurrencyInstance(new ULocale("ja_JP"));
2773 String text1 = cfmt.format(value);
2775 // Reset the same currency and format the test value again
2776 cfmt.setCurrency(cfmt.getCurrency());
2777 String text2 = cfmt.format(value);
2779 // output1 and output2 must be identical
2780 if (!text1.equals(text2)) {
2781 errln("NumberFormat.format() should return the same result - text1="
2782 + text1 + " text2=" + text2);
2787 * Testing rounding to negative zero problem
2788 * reported by ticket#7609
2790 public void TestNegZeroRounding() {
2792 DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
2793 df.setRoundingMode(MathContext.ROUND_HALF_UP);
2794 df.setMinimumFractionDigits(1);
2795 df.setMaximumFractionDigits(1);
2796 String text1 = df.format(-0.01);
2798 df.setRoundingIncrement(0.1);
2799 String text2 = df.format(-0.01);
2801 // output1 and output2 must be identical
2802 if (!text1.equals(text2)) {
2803 errln("NumberFormat.format() should return the same result - text1="
2804 + text1 + " text2=" + text2);
2809 public void TestCurrencyAmountCoverage() {
2810 CurrencyAmount ca, cb;
2813 ca = new CurrencyAmount(null, null);
2814 errln("NullPointerException should have been thrown.");
2815 } catch (NullPointerException ex) {
2818 ca = new CurrencyAmount(new Integer(0), null);
2819 errln("NullPointerException should have been thrown.");
2820 } catch (NullPointerException ex) {
2823 ca = new CurrencyAmount(new Integer(0), Currency.getInstance(new ULocale("ja_JP")));
2824 cb = new CurrencyAmount(new Integer(1), Currency.getInstance(new ULocale("ja_JP")));
2825 if (ca.equals(null)) {
2826 errln("Comparison should return false.");
2828 if (!ca.equals(ca)) {
2829 errln("Comparision should return true.");
2831 if (ca.equals(cb)) {
2832 errln("Comparison should return false.");
2836 public void TestExponentParse() {
2837 ParsePosition parsePos = new ParsePosition(0);
2838 DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
2839 DecimalFormat fmt = new DecimalFormat("#####", symbols);
2840 Number result = fmt.parse("5.06e-27", parsePos);
2841 if ( result.doubleValue() != 5.06E-27 || parsePos.getIndex() != 8) {
2842 errln("ERROR: ERROR: parse failed - expected 5.06E-27, 8; got " + result.doubleValue() + ", " + parsePos.getIndex());
2846 public void TestExplicitParents() {
2847 // We use these for testing because decimal and grouping separators will be inherited from es_419
2848 // starting with CLDR 2.0
2850 "es", "CO", "", "1.250,75",
2851 "es", "CR", "", "1.250,75",
2852 "es", "ES", "", "1.250,75",
2853 "es", "GQ", "", "1.250,75",
2854 "es", "MX", "", "1,250.75",
2855 "es", "US", "", "1,250.75",
2856 "es", "VE", "", "1.250,75",
2860 for (int i=0; i<DATA.length; i+=4) {
2861 Locale locale = new Locale(DATA[i], DATA[i+1], DATA[i+2]);
2862 NumberFormat fmt = NumberFormat.getInstance(locale);
2863 String s = fmt.format(1250.75);
2864 if (s.equals(DATA[i+3])) {
2865 logln("Ok: 1250.75 x " + locale + " => " + s);
2867 errln("FAIL: 1250.75 x " + locale + " => " + s +
2868 ", expected " + DATA[i+3]);