3 *******************************************************************************
4 * Copyright (C) 2001-2009, 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 com.ibm.icu.dev.test.TestUtil;
17 import com.ibm.icu.text.*;
18 import com.ibm.icu.text.NumberFormat.*;
19 import com.ibm.icu.util.*;
20 import com.ibm.icu.impl.LocaleUtility;
21 import com.ibm.icu.impl.data.ResourceReader;
22 import com.ibm.icu.impl.data.TokenIterator;
23 import com.ibm.icu.impl.Utility;
24 import com.ibm.icu.math.BigDecimal;
26 import java.lang.Double;
27 import java.math.BigInteger;
28 import java.text.FieldPosition;
29 import java.text.ParsePosition;
30 import java.text.ParseException;
31 import java.util.Locale;
32 import java.util.ArrayList;
34 public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
36 public static void main(String[] args) throws Exception {
37 new NumberFormatTest().run(args);
40 // Test various patterns
41 public void TestPatterns() {
43 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
44 final String pat[] = { "#.#", "#.", ".#", "#" };
45 int pat_length = pat.length;
46 final String newpat[] = { "#0.#", "#0.", "#.0", "#" };
47 final String num[] = { "0", "0.", ".0", "0" };
48 for (int i=0; i<pat_length; ++i)
50 DecimalFormat fmt = new DecimalFormat(pat[i], sym);
51 String newp = fmt.toPattern();
52 if (!newp.equals(newpat[i]))
53 errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
54 "; " + newp + " seen instead");
56 String s = ((NumberFormat)fmt).format(0);
57 if (!s.equals(num[i]))
59 errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
60 "; " + s + " seen instead");
61 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
63 // BigInteger 0 - ticket#4731
64 s = ((NumberFormat)fmt).format(BigInteger.ZERO);
65 if (!s.equals(num[i]))
67 errln("FAIL: Pattern " + pat[i] + " should format BigInteger zero as " + num[i] +
68 "; " + s + " seen instead");
69 logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
74 // Test exponential pattern
75 public void TestExponential() {
77 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
78 final String pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
79 int pat_length = pat.length;
81 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
82 int val_length = val.length;
83 final String valFormat[] = {
85 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
87 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
89 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
91 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]" };
94 0.01234, 123460000, 1.23E300, -3.1416E-271,
95 0.01234, 123460000, 1.23E300, -3.1416E-271,
96 0.01234, 123456800, 1.23E300, -3.141593E-271,
97 0.01234, 123500000, 1.23E300, -3.142E-271,
98 };*/ //The variable is never used
100 int lval[] = { 0, -1, 1, 123456789 };
101 int lval_length = lval.length;
102 final String lvalFormat[] = {
104 "0E0", "-1E0", "1E0", "1.2346E8",
106 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
108 "0E000", "-1E000", "1E000", "123.4568E006",
110 "0E0", "[1E0]", "1E0", "1.235E8" };
118 int ival = 0, ilval = 0;
119 for (int p = 0; p < pat_length; ++p) {
120 DecimalFormat fmt = new DecimalFormat(pat[p], sym);
121 logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" + fmt.toPattern() + "\"");
123 for (v = 0; v < val_length; ++v) {
125 s = ((NumberFormat) fmt).format(val[v]);
126 logln(" " + val[v] + " -format-> " + s);
127 if (!s.equals(valFormat[v + ival]))
128 errln("FAIL: Expected " + valFormat[v + ival]);
130 ParsePosition pos = new ParsePosition(0);
131 double a = fmt.parse(s, pos).doubleValue();
132 if (pos.getIndex() == s.length()) {
133 logln(" -parse-> " + Double.toString(a));
134 // Use epsilon comparison as necessary
136 errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
138 for (v = 0; v < lval_length; ++v) {
140 s = ((NumberFormat) fmt).format(lval[v]);
141 logln(" " + lval[v] + "L -format-> " + s);
142 if (!s.equals(lvalFormat[v + ilval]))
143 errln("ERROR: Expected " + lvalFormat[v + ilval] + " Got: " + s);
145 ParsePosition pos = new ParsePosition(0);
147 Number A = fmt.parse(s, pos);
150 if (pos.getIndex() == s.length()) {
151 logln(" -parse-> " + a);
152 if (a != lvalParse[v + ilval])
153 errln("FAIL: Expected " + lvalParse[v + ilval]);
155 errln("FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + Long.toString(a));
157 errln("Fail to parse the string: " + s);
161 ilval += lval_length;
165 // Test the handling of quotes
166 public void TestQuotes() {
169 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
170 pat = new StringBuffer("a'fo''o'b#");
171 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
172 String s = ((NumberFormat)fmt).format(123);
173 logln("Pattern \"" + pat + "\"");
174 logln(" Format 123 . " + s);
175 if (!s.equals("afo'ob123"))
176 errln("FAIL: Expected afo'ob123");
179 pat = new StringBuffer("a''b#");
180 fmt = new DecimalFormat(pat.toString(), sym);
181 s = ((NumberFormat)fmt).format(123);
182 logln("Pattern \"" + pat + "\"");
183 logln(" Format 123 . " + s);
184 if (!s.equals("a'b123"))
185 errln("FAIL: Expected a'b123");
188 public void TestParseCurrencyTrailingSymbol() {
189 // see sun bug 4709840
190 NumberFormat fmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
191 float val = 12345.67f;
192 String str = fmt.format(val);
193 logln("val: " + val + " str: " + str);
195 Number num = fmt.parse(str);
196 logln("num: " + num);
197 } catch (ParseException e) {
198 errln("parse of '" + str + "' threw exception: " + e);
203 * Test the handling of the currency symbol in patterns.
205 public void TestCurrencySign() {
206 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
207 StringBuffer pat = new StringBuffer("");
208 char currency = 0x00A4;
209 // "\xA4#,##0.00;-\xA4#,##0.00"
210 pat.append(currency).append("#,##0.00;-").append(currency).append("#,##0.00");
211 DecimalFormat fmt = new DecimalFormat(pat.toString(), sym);
212 String s = ((NumberFormat) fmt).format(1234.56);
213 pat = new StringBuffer("");
214 logln("Pattern \"" + fmt.toPattern() + "\"");
215 logln(" Format " + 1234.56 + " . " + s);
216 if (!s.equals("$1,234.56"))
217 errln("FAIL: Expected $1,234.56");
219 s = ((NumberFormat) fmt).format(-1234.56);
220 logln(" Format " + Double.toString(-1234.56) + " . " + s);
221 if (!s.equals("-$1,234.56"))
222 errln("FAIL: Expected -$1,234.56");
224 pat = new StringBuffer("");
225 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
226 pat.append(currency).append(currency).append(" #,##0.00;").append(currency).append(currency).append(" -#,##0.00");
227 fmt = new DecimalFormat(pat.toString(), sym);
229 s = ((NumberFormat) fmt).format(1234.56);
230 logln("Pattern \"" + fmt.toPattern() + "\"");
231 logln(" Format " + Double.toString(1234.56) + " . " + s);
233 if (!s.equals("USD 1,234.56"))
234 errln("FAIL: Expected USD 1,234.56");
236 s = ((NumberFormat) fmt).format(-1234.56);
237 logln(" Format " + Double.toString(-1234.56) + " . " + s);
238 if (!s.equals("USD -1,234.56"))
239 errln("FAIL: Expected USD -1,234.56");
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 = Utility.replaceAll(pat, "\u00A4", doubleCurrencyStr);
312 pat = Utility.replaceAll(pat, "\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\u00a0DM",
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 \u0420\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 \u0420\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 \u0420\u043E\u0441\u0441\u0438\u0439\u0441\u043A\u0438\u0445 \u0440\u0443\u0431\u043B\u0435\u0439"},
493 // test locale without currency information
494 {"ti_ET", "-1.23", "USD", "-US$1.23", "-USD1.23", "-1.23 USD"},
495 // test choice format
496 {"es_AR", "1", "INR", "Rs\u00A01,00", "INR\u00A01,00", "1,00 rupia india"},
497 {"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"},
500 for (int i=0; i<DATA.length; ++i) {
501 for (int k = NumberFormat.CURRENCYSTYLE;
502 k <= NumberFormat.PLURALCURRENCYSTYLE;
504 // k represents currency format style.
505 if ( k != NumberFormat.CURRENCYSTYLE &&
506 k != NumberFormat.ISOCURRENCYSTYLE &&
507 k != NumberFormat.PLURALCURRENCYSTYLE ) {
510 String localeString = DATA[i][0];
511 Double numberToBeFormat = new Double(DATA[i][1]);
512 String currencyISOCode = DATA[i][2];
513 ULocale locale = new ULocale(localeString);
514 NumberFormat numFmt = NumberFormat.getInstance(locale, k);
515 numFmt.setCurrency(Currency.getInstance(currencyISOCode));
516 String strBuf = numFmt.format(numberToBeFormat);
517 int resultDataIndex = k-1;
518 if ( k == NumberFormat.CURRENCYSTYLE ) {
519 resultDataIndex = k+2;
521 // DATA[i][resultDataIndex] is the currency format result
522 // using 'k' currency style.
523 String formatResult = DATA[i][resultDataIndex];
524 if (!strBuf.equals(formatResult)) {
525 errln("FAIL: Expected " + formatResult + " actual: " + Utility.escape(strBuf));
528 // test parsing, and test parsing for all currency formats.
529 for (int j = 3; j < 6; ++j) {
530 // DATA[i][3] is the currency format result using
531 // CURRENCYSTYLE formatter.
532 // DATA[i][4] is the currency format result using
533 // ISOCURRENCYSTYLE formatter.
534 // DATA[i][5] is the currency format result using
535 // PLURALCURRENCYSTYLE formatter.
536 String oneCurrencyFormatResult = DATA[i][j];
537 Number val = numFmt.parse(oneCurrencyFormatResult);
538 if (val.doubleValue() != numberToBeFormat.doubleValue()) {
539 errln("FAIL: getCurrencyFormat of locale " + localeString + " failed roundtripping the number. val=" + val + "; expected: " + numberToBeFormat);
543 catch (ParseException e) {
544 errln("FAIL: " + e.getMessage());
551 public void TestMiscCurrencyParsing() {
553 // each has: string to be parsed, parsed position, error position
555 {"1.00 UAE dirha", "0", "4"},
556 {"1.00 us dollar", "14", "-1"},
557 {"1.00 US DOLLAR", "14", "-1"},
558 {"1.00 usd", "0", "4"},
560 ULocale locale = new ULocale("en_US");
561 for (int i=0; i<DATA.length; ++i) {
562 String stringToBeParsed = DATA[i][0];
563 int parsedPosition = Integer.parseInt(DATA[i][1]);
564 int errorIndex = Integer.parseInt(DATA[i][2]);
565 NumberFormat numFmt = NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
566 ParsePosition parsePosition = new ParsePosition(0);
567 Number val = numFmt.parse(stringToBeParsed, parsePosition);
568 if (parsePosition.getIndex() != parsedPosition ||
569 parsePosition.getErrorIndex() != errorIndex) {
570 errln("FAIL: parse failed. expected error position: " + errorIndex + "; actual: " + parsePosition.getErrorIndex());
571 errln("FAIL: parse failed. expected position: " + parsedPosition +"; actual: " + parsePosition.getIndex());
573 if (parsePosition.getErrorIndex() == -1 &&
574 val.doubleValue() != 1.00) {
575 errln("FAIL: parse failed. expected 1.00, actual:" + val);
582 * Test the Currency object handling, new as of ICU 2.2.
584 public void TestCurrencyObject() {
586 NumberFormat.getCurrencyInstance(Locale.US);
588 expectCurrency(fmt, null, 1234.56, "$1,234.56");
590 expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
591 1234.56, "\u20AC1,234.56"); // Euro
593 expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
594 1234.56, "\u00A51,235"); // Yen
596 expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
597 1234.56, "Fr.1,234.55"); // 0.05 rounding
599 expectCurrency(fmt, Currency.getInstance(Locale.US),
600 1234.56, "$1,234.56");
602 fmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
604 expectCurrency(fmt, null, 1234.56, "1 234,56 \u20AC");
606 expectCurrency(fmt, Currency.getInstance(Locale.JAPAN),
607 1234.56, "1 235 \u00A5JP"); // Yen
609 expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
610 1234.56, "1 234,55 CHF"); // 0.25 rounding
612 expectCurrency(fmt, Currency.getInstance(Locale.US),
613 1234.56, "1 234,56 $US");
615 expectCurrency(fmt, Currency.getInstance(Locale.FRANCE),
616 1234.56, "1 234,56 \u20AC"); // Euro
619 public void TestCurrencyPatterns() {
621 Locale[] locs = NumberFormat.getAvailableLocales();
622 for (i=0; i<locs.length; ++i) {
623 NumberFormat nf = NumberFormat.getCurrencyInstance(locs[i]);
624 // Make sure currency formats do not have a variable number
625 // of fraction digits
626 int min = nf.getMinimumFractionDigits();
627 int max = nf.getMaximumFractionDigits();
629 String a = nf.format(1.0);
630 String b = nf.format(1.125);
631 errln("FAIL: " + locs[i] +
632 " min fraction digits != max fraction digits; "+
634 "; x 1.125 => " + b);
637 // Make sure EURO currency formats have exactly 2 fraction digits
638 if (nf instanceof DecimalFormat) {
639 Currency curr = ((DecimalFormat) nf).getCurrency();
640 if (curr != null && "EUR".equals(curr.getCurrencyCode())) {
641 if (min != 2 || max != 2) {
642 String a = nf.format(1.0);
643 errln("FAIL: " + locs[i] +
644 " is a EURO format but it does not have 2 fraction digits; "+
654 * Do rudimentary testing of parsing.
656 public void TestParse() {
658 DecimalFormat format = new DecimalFormat("00");
661 aNumber = format.parse(arg).doubleValue();
662 } catch (ParseException e) {
663 System.out.println(e);
665 logln("parse(" + arg + ") = " + aNumber);
669 * Test proper rounding by the format method.
671 public void TestRounding487() {
673 NumberFormat nf = NumberFormat.getInstance();
674 roundingTest(nf, 0.00159999, 4, "0.0016");
675 roundingTest(nf, 0.00995, 4, "0.01");
677 roundingTest(nf, 12.3995, 3, "12.4");
679 roundingTest(nf, 12.4999, 0, "12");
680 roundingTest(nf, - 19.5, 0, "-20");
685 * Test the functioning of the secondary grouping value.
687 public void TestSecondaryGrouping() {
689 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
690 DecimalFormat f = new DecimalFormat("#,##,###", US);
692 expect(f, 123456789L, "12,34,56,789");
693 expectPat(f, "#,##,###");
694 f.applyPattern("#,###");
696 f.setSecondaryGroupingSize(4);
697 expect(f, 123456789L, "12,3456,789");
698 expectPat(f, "#,####,###");
699 NumberFormat g = NumberFormat.getInstance(new Locale("hi", "IN"));
702 long l = 1876543210L;
705 // expect "1,87,65,43,210", but with Hindi digits
708 if (out.length() != 14) {
711 for (int i = 0; i < out.length(); ++i) {
712 boolean expectGroup = false;
721 // Later -- fix this to get the actual grouping
722 // character from the resource bundle.
723 boolean isGroup = (out.charAt(i) == 0x002C);
724 if (isGroup != expectGroup) {
731 errln("FAIL Expected "+ l + " x hi_IN . \"1,87,65,43,210\" (with Hindi digits), got \""
734 logln("Ok " + l + " x hi_IN . \"" + out + "\"");
738 public void roundingTest(NumberFormat nf, double x, int maxFractionDigits, final String expected) {
739 nf.setMaximumFractionDigits(maxFractionDigits);
740 String out = nf.format(x);
741 logln(x + " formats with " + maxFractionDigits + " fractional digits to " + out);
742 if (!out.equals(expected))
743 errln("FAIL: Expected " + expected);
747 * Upgrade to alphaWorks
749 public void TestExponent() {
750 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
751 DecimalFormat fmt1 = new DecimalFormat("0.###E0", US);
752 DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US);
754 expect2(fmt1, n, "1.234E3");
755 expect2(fmt2, n, "1.234E+3");
756 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
761 * Upgrade to alphaWorks
763 public void TestScientific() {
765 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
767 // Test pattern round-trip
768 final String PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
769 int PAT_length = PAT.length;
771 // min int, max int, min frac, max frac
773 1, 1, 0, 4, // "0.####E0"
774 2, 2, 3, 3, // "00.000E00"
775 1, 3, 0, 4, // "##0.####E000"
776 1, 1, 0, 3, // "0.###E0;[0.###E0]"
778 for (int i = 0; i < PAT_length; ++i) {
780 DecimalFormat df = new DecimalFormat(pat, US);
781 String pat2 = df.toPattern();
782 if (pat.equals(pat2)) {
783 logln("Ok Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
785 errln("FAIL Pattern rt \"" + pat + "\" . \"" + pat2 + "\"");
787 // Make sure digit counts match what we expect
788 if (df.getMinimumIntegerDigits() != DIGITS[4 * i]
789 || df.getMaximumIntegerDigits() != DIGITS[4 * i + 1]
790 || df.getMinimumFractionDigits() != DIGITS[4 * i + 2]
791 || df.getMaximumFractionDigits() != DIGITS[4 * i + 3]) {
792 errln("FAIL \""+ pat+ "\" min/max int; min/max frac = "
793 + df.getMinimumIntegerDigits() + "/"
794 + df.getMaximumIntegerDigits() + ";"
795 + df.getMinimumFractionDigits() + "/"
796 + df.getMaximumFractionDigits() + ", expect "
797 + DIGITS[4 * i] + "/"
798 + DIGITS[4 * i + 1] + ";"
799 + DIGITS[4 * i + 2] + "/"
800 + DIGITS[4 * i + 3]);
804 expect2(new DecimalFormat("#E0", US), 12345.0, "1.2345E4");
805 expect(new DecimalFormat("0E0", US), 12345.0, "1E4");
807 // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
808 // so result = 1.234568E4 not 1.2345678901E4
809 //when the pattern problem is finalized, delete comment mark'//'
810 //of the following code
811 expect2(NumberFormat.getScientificInstance(Locale.US), 12345.678901, "1.2345678901E4");
812 logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
813 expect2(NumberFormat.getScientificInstance(ULocale.US), 12345.678901, "1.2345678901E4");
815 expect(new DecimalFormat("##0.###E0", US), 12345.0, "12.34E3");
816 expect(new DecimalFormat("##0.###E0", US), 12345.00001, "12.35E3");
817 expect2(new DecimalFormat("##0.####E0", US), 12345, "12.345E3");
819 // pattern of NumberFormat.getScientificInstance(Locale.US) = "0.######E0" not "#E0"
820 // so result = 1.234568E4 not 1.2345678901E4
821 expect2(NumberFormat.getScientificInstance(Locale.FRANCE), 12345.678901, "1,2345678901E4");
822 logln("Testing NumberFormat.getScientificInstance(ULocale) ...");
823 expect2(NumberFormat.getScientificInstance(ULocale.FRANCE), 12345.678901, "1,2345678901E4");
825 expect(new DecimalFormat("##0.####E0", US), 789.12345e-9, "789.12E-9");
826 expect2(new DecimalFormat("##0.####E0", US), 780.e-9, "780E-9");
827 expect(new DecimalFormat(".###E0", US), 45678.0, ".457E5");
828 expect2(new DecimalFormat(".###E0", US), 0, ".0E0");
830 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
831 new DecimalFormat("##E0", US),
832 new DecimalFormat("####E0", US),
833 new DecimalFormat("0E0", US),
834 new DecimalFormat("00E0", US),
835 new DecimalFormat("000E0", US),
838 new String[] { "4.5678E7",
847 ! Unroll this test into individual tests below...
850 expect2(new DecimalFormat("#E0", US), 45678000, "4.5678E7");
851 expect2(new DecimalFormat("##E0", US), 45678000, "45.678E6");
852 expect2(new DecimalFormat("####E0", US), 45678000, "4567.8E4");
853 expect(new DecimalFormat("0E0", US), 45678000, "5E7");
854 expect(new DecimalFormat("00E0", US), 45678000, "46E6");
855 expect(new DecimalFormat("000E0", US), 45678000, "457E5");
857 expect(new DecimalFormat("###E0", US, status),
858 new Object[] { new Double(0.0000123), "12.3E-6",
859 new Double(0.000123), "123E-6",
860 new Double(0.00123), "1.23E-3",
861 new Double(0.0123), "12.3E-3",
862 new Double(0.123), "123E-3",
863 new Double(1.23), "1.23E0",
864 new Double(12.3), "12.3E0",
865 new Double(123), "123E0",
866 new Double(1230), "1.23E3",
869 ! Unroll this test into individual tests below...
872 expect2(new DecimalFormat("###E0", US), 0.0000123, "12.3E-6");
873 expect2(new DecimalFormat("###E0", US), 0.000123, "123E-6");
874 expect2(new DecimalFormat("###E0", US), 0.00123, "1.23E-3");
875 expect2(new DecimalFormat("###E0", US), 0.0123, "12.3E-3");
876 expect2(new DecimalFormat("###E0", US), 0.123, "123E-3");
877 expect2(new DecimalFormat("###E0", US), 1.23, "1.23E0");
878 expect2(new DecimalFormat("###E0", US), 12.3, "12.3E0");
879 expect2(new DecimalFormat("###E0", US), 123.0, "123E0");
880 expect2(new DecimalFormat("###E0", US), 1230.0, "1.23E3");
882 expect(new DecimalFormat("0.#E+00", US, status),
883 new Object[] { new Double(0.00012), "1.2E-04",
884 new Long(12000), "1.2E+04",
887 ! Unroll this test into individual tests below...
890 expect2(new DecimalFormat("0.#E+00", US), 0.00012, "1.2E-04");
891 expect2(new DecimalFormat("0.#E+00", US), 12000, "1.2E+04");
895 * Upgrade to alphaWorks
897 public void TestPad() {
899 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
900 expect2(new DecimalFormat("*^##.##", US), 0, "^^^^0");
901 expect2(new DecimalFormat("*^##.##", US), -1.3, "^-1.3");
903 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
905 "0.0E0______ g-m/s^2");
907 new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
909 "333.333E-3_ g-m/s^2");
910 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US), 0, "0.0______ g-m/s^2");
912 new DecimalFormat("##0.0####*_ 'g-m/s^2'", US),
914 "0.33333__ g-m/s^2");
916 // Test padding before a sign
917 final String formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
918 expect2(new DecimalFormat(formatStr, US), -10, "xxxxxxxxxx(10.0)");
919 expect2(new DecimalFormat(formatStr, US), -1000, "xxxxxxx(1,000.0)");
920 expect2(new DecimalFormat(formatStr, US), -1000000, "xxx(1,000,000.0)");
921 expect2(new DecimalFormat(formatStr, US), -100.37, "xxxxxxxx(100.37)");
922 expect2(new DecimalFormat(formatStr, US), -10456.37, "xxxxx(10,456.37)");
923 expect2(new DecimalFormat(formatStr, US), -1120456.37, "xx(1,120,456.37)");
924 expect2(new DecimalFormat(formatStr, US), -112045600.37, "(112,045,600.37)");
925 expect2(new DecimalFormat(formatStr, US), -1252045600.37, "(1,252,045,600.37)");
927 expect2(new DecimalFormat(formatStr, US), 10, "xxxxxxxxxxxx10.0");
928 expect2(new DecimalFormat(formatStr, US), 1000, "xxxxxxxxx1,000.0");
929 expect2(new DecimalFormat(formatStr, US), 1000000, "xxxxx1,000,000.0");
930 expect2(new DecimalFormat(formatStr, US), 100.37, "xxxxxxxxxx100.37");
931 expect2(new DecimalFormat(formatStr, US), 10456.37, "xxxxxxx10,456.37");
932 expect2(new DecimalFormat(formatStr, US), 1120456.37, "xxxx1,120,456.37");
933 expect2(new DecimalFormat(formatStr, US), 112045600.37, "xx112,045,600.37");
934 expect2(new DecimalFormat(formatStr, US), 10252045600.37, "10,252,045,600.37");
936 // Test padding between a sign and a number
937 final String formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
938 expect2(new DecimalFormat(formatStr2, US), -10, "(10.0xxxxxxxxxx)");
939 expect2(new DecimalFormat(formatStr2, US), -1000, "(1,000.0xxxxxxx)");
940 expect2(new DecimalFormat(formatStr2, US), -1000000, "(1,000,000.0xxx)");
941 expect2(new DecimalFormat(formatStr2, US), -100.37, "(100.37xxxxxxxx)");
942 expect2(new DecimalFormat(formatStr2, US), -10456.37, "(10,456.37xxxxx)");
943 expect2(new DecimalFormat(formatStr2, US), -1120456.37, "(1,120,456.37xx)");
944 expect2(new DecimalFormat(formatStr2, US), -112045600.37, "(112,045,600.37)");
945 expect2(new DecimalFormat(formatStr2, US), -1252045600.37, "(1,252,045,600.37)");
947 expect2(new DecimalFormat(formatStr2, US), 10, "10.0xxxxxxxxxxxx");
948 expect2(new DecimalFormat(formatStr2, US), 1000, "1,000.0xxxxxxxxx");
949 expect2(new DecimalFormat(formatStr2, US), 1000000, "1,000,000.0xxxxx");
950 expect2(new DecimalFormat(formatStr2, US), 100.37, "100.37xxxxxxxxxx");
951 expect2(new DecimalFormat(formatStr2, US), 10456.37, "10,456.37xxxxxxx");
952 expect2(new DecimalFormat(formatStr2, US), 1120456.37, "1,120,456.37xxxx");
953 expect2(new DecimalFormat(formatStr2, US), 112045600.37, "112,045,600.37xx");
954 expect2(new DecimalFormat(formatStr2, US), 10252045600.37, "10,252,045,600.37");
956 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
957 DecimalFormat fmt = new DecimalFormat("#", US);
958 char padString = 'P';
959 fmt.setPadCharacter(padString);
960 expectPad(fmt, "*P##.##", DecimalFormat.PAD_BEFORE_PREFIX, 5, padString);
961 fmt.setPadCharacter('^');
962 expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^');
963 //commented untill implementation is complete
964 /* fmt.setPadCharacter((UnicodeString)"^^^");
965 expectPad(fmt, "*^^^#", DecimalFormat.kPadBeforePrefix, 3, (UnicodeString)"^^^");
967 padString.append((UChar)0x0061);
968 padString.append((UChar)0x0302);
969 fmt.setPadCharacter(padString);
970 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
971 UnicodeString pattern(patternChars);
972 expectPad(fmt, pattern , DecimalFormat.kPadBeforePrefix, 4, padString);
977 * Upgrade to alphaWorks
979 public void TestPatterns2() {
980 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
981 DecimalFormat fmt = new DecimalFormat("#", US);
983 char hat = 0x005E; /*^*/
985 expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, hat);
986 expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, hat);
987 expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, hat);
988 expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, hat);
989 expectPad(fmt, "$*^$#", -1);
990 expectPad(fmt, "#$*^$", -1);
991 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX, 12, (char) 0x0078 /*x*/);
992 expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX, 3, (char) 0x0078 /*x*/);
993 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX, 10, (char) 0x0061 /*a*/);
995 fmt.applyPattern("AA#,##0.00ZZ");
996 fmt.setPadCharacter(hat);
998 fmt.setFormatWidth(10);
1000 fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX);
1001 expectPat(fmt, "*^AA#,##0.00ZZ");
1003 fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX);
1004 expectPat(fmt, "AA#,##0.00*^ZZ");
1006 fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX);
1007 expectPat(fmt, "AA#,##0.00ZZ*^");
1010 String exp = "AA*^#,##0.00ZZ";
1011 fmt.setFormatWidth(12);
1012 fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX);
1013 expectPat(fmt, exp);
1015 fmt.setFormatWidth(13);
1017 expectPat(fmt, "AA*^##,##0.00ZZ");
1019 fmt.setFormatWidth(14);
1021 expectPat(fmt, "AA*^###,##0.00ZZ");
1023 fmt.setFormatWidth(15);
1025 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1027 fmt.setFormatWidth(16);
1028 // 12 34567890123456
1029 expectPat(fmt, "AA*^#,###,##0.00ZZ");
1032 public void TestRegistration() {
1033 final ULocale SRC_LOC = ULocale.FRANCE;
1034 final ULocale SWAP_LOC = ULocale.US;
1036 class TestFactory extends SimpleNumberFormatFactory {
1037 NumberFormat currencyStyle;
1040 super(SRC_LOC, true);
1041 currencyStyle = NumberFormat.getIntegerInstance(SWAP_LOC);
1044 public NumberFormat createFormat(ULocale loc, int formatType) {
1045 if (formatType == FORMAT_CURRENCY) {
1046 return currencyStyle;
1052 NumberFormat f0 = NumberFormat.getIntegerInstance(SWAP_LOC);
1053 NumberFormat f1 = NumberFormat.getIntegerInstance(SRC_LOC);
1054 NumberFormat f2 = NumberFormat.getCurrencyInstance(SRC_LOC);
1055 Object key = NumberFormat.registerFactory(new TestFactory());
1056 NumberFormat f3 = NumberFormat.getCurrencyInstance(SRC_LOC);
1057 NumberFormat f4 = NumberFormat.getIntegerInstance(SRC_LOC);
1058 NumberFormat.unregister(key); // restore for other tests
1059 NumberFormat f5 = NumberFormat.getCurrencyInstance(SRC_LOC);
1061 float n = 1234.567f;
1062 logln("f0 swap int: " + f0.format(n));
1063 logln("f1 src int: " + f1.format(n));
1064 logln("f2 src cur: " + f2.format(n));
1065 logln("f3 reg cur: " + f3.format(n));
1066 logln("f4 reg int: " + f4.format(n));
1067 logln("f5 unreg cur: " + f5.format(n));
1069 if (!f3.format(n).equals(f0.format(n))) {
1070 errln("registered service did not match");
1072 if (!f4.format(n).equals(f1.format(n))) {
1073 errln("registered service did not inherit");
1075 if (!f5.format(n).equals(f2.format(n))) {
1076 errln("unregistered service did not match original");
1080 public void TestScientific2() {
1082 DecimalFormat fmt = (DecimalFormat)NumberFormat.getCurrencyInstance();
1083 Number num = new Double(12.34);
1084 expect(fmt, num, "$12.34");
1085 fmt.setScientificNotation(true);
1086 expect(fmt, num, "$1.23E1");
1087 fmt.setScientificNotation(false);
1088 expect(fmt, num, "$12.34");
1091 public void TestScientificGrouping() {
1093 DecimalFormat fmt = new DecimalFormat("###.##E0");
1094 expect(fmt, .01234, "12.3E-3");
1095 expect(fmt, .1234, "123E-3");
1096 expect(fmt, 1.234, "1.23E0");
1097 expect(fmt, 12.34, "12.3E0");
1098 expect(fmt, 123.4, "123E0");
1099 expect(fmt, 1234, "1.23E3");
1102 // additional coverage tests
1104 // sigh, can't have static inner classes, why not?
1106 static final class PI extends Number {
1110 private static final long serialVersionUID = -305601227915602172L;
1113 public int intValue() { return (int)Math.PI; }
1114 public long longValue() { return (long)Math.PI; }
1115 public float floatValue() { return (float)Math.PI; }
1116 public double doubleValue() { return (double)Math.PI; }
1117 public byte byteValue() { return (byte)Math.PI; }
1118 public short shortValue() { return (short)Math.PI; }
1120 public static final Number INSTANCE = new PI();
1123 public void TestCoverage() {
1124 NumberFormat fmt = NumberFormat.getNumberInstance(); // default locale
1125 logln(fmt.format(new BigInteger("1234567890987654321234567890987654321", 10)));
1127 fmt = NumberFormat.getScientificInstance(); // default locale
1129 logln(fmt.format(PI.INSTANCE));
1132 logln(fmt.format("12345"));
1133 errln("numberformat of string did not throw exception");
1135 catch (Exception e) {
1136 logln("PASS: numberformat of string failed as expected");
1139 int hash = fmt.hashCode();
1140 logln("hash code " + hash);
1142 logln("compare to string returns: " + fmt.equals(""));
1144 // For ICU 2.6 - alan
1145 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1146 DecimalFormat df = new DecimalFormat("'*&'' '\u00A4' ''&*' #,##0.00", US);
1147 df.setCurrency(Currency.getInstance("INR"));
1148 expect2(df, 1.0, "*&' Rs '&* 1.00");
1149 expect2(df, -2.0, "-*&' Rs '&* 2.00");
1150 df.applyPattern("#,##0.00 '*&'' '\u00A4' ''&*'");
1151 expect2(df, 2.0, "2.00 *&' Rs '&*");
1152 expect2(df, -1.0, "-1.00 *&' Rs '&*");
1154 //#if defined(FOUNDATION10)
1155 //## com.ibm.icu.math.BigDecimal r = df.getRoundingIncrement();
1157 java.math.BigDecimal r = df.getRoundingIncrement();
1160 errln("FAIL: rounding = " + r + ", expect null");
1163 if (df.isScientificNotation()) {
1164 errln("FAIL: isScientificNotation = true, expect false");
1167 df.applyPattern("0.00000");
1168 df.setScientificNotation(true);
1169 if (!df.isScientificNotation()) {
1170 errln("FAIL: isScientificNotation = false, expect true");
1172 df.setMinimumExponentDigits((byte)2);
1173 if (df.getMinimumExponentDigits() != 2) {
1174 errln("FAIL: getMinimumExponentDigits = " +
1175 df.getMinimumExponentDigits() + ", expect 2");
1177 df.setExponentSignAlwaysShown(true);
1178 if (!df.isExponentSignAlwaysShown()) {
1179 errln("FAIL: isExponentSignAlwaysShown = false, expect true");
1181 df.setSecondaryGroupingSize(0);
1182 if (df.getSecondaryGroupingSize() != 0) {
1183 errln("FAIL: getSecondaryGroupingSize = " +
1184 df.getSecondaryGroupingSize() + ", expect 0");
1186 expect2(df, 3.14159, "3.14159E+00");
1188 // DecimalFormatSymbols#getInstance
1189 DecimalFormatSymbols decsym1 = DecimalFormatSymbols.getInstance();
1190 DecimalFormatSymbols decsym2 = new DecimalFormatSymbols();
1191 if (!decsym1.equals(decsym2)) {
1192 errln("FAIL: DecimalFormatSymbols returned by getInstance()" +
1193 "does not match new DecimalFormatSymbols().");
1195 decsym1 = DecimalFormatSymbols.getInstance(Locale.JAPAN);
1196 decsym2 = DecimalFormatSymbols.getInstance(ULocale.JAPAN);
1197 if (!decsym1.equals(decsym2)) {
1198 errln("FAIL: DecimalFormatSymbols returned by getInstance(Locale.JAPAN)" +
1199 "does not match the one returned by getInstance(ULocale.JAPAN).");
1202 // DecimalFormatSymbols#getAvailableLocales/#getAvailableULocales
1203 Locale[] allLocales = DecimalFormatSymbols.getAvailableLocales();
1204 if (allLocales.length == 0) {
1205 errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1207 logln("PASS: " + allLocales.length +
1208 " available locales returned by DecimalFormatSymbols.getAvailableLocales");
1210 ULocale[] allULocales = DecimalFormatSymbols.getAvailableULocales();
1211 if (allULocales.length == 0) {
1212 errln("FAIL: Got a empty list for DecimalFormatSymbols.getAvailableLocales");
1214 logln("PASS: " + allULocales.length +
1215 " available locales returned by DecimalFormatSymbols.getAvailableULocales");
1219 public void TestWhiteSpaceParsing() {
1220 DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
1221 DecimalFormat fmt = new DecimalFormat("a b#0c ", US);
1223 expect(fmt, "a b1234c ", n);
1224 expect(fmt, "a b1234c ", n);
1228 * Test currencies whose display name is a ChoiceFormat.
1230 public void TestComplexCurrency() {
1231 // CLDR No Longer uses complex currency symbols.
1232 // Skipping this test.
1233 // Locale loc = new Locale("kn", "IN", "");
1234 // NumberFormat fmt = NumberFormat.getCurrencyInstance(loc);
1236 // expect2(fmt, 1.0, "Re.\u00a01.00");
1237 // expect(fmt, 1.001, "Re.\u00a01.00"); // tricky
1238 // expect2(fmt, 12345678.0, "Rs.\u00a01,23,45,678.00");
1239 // expect2(fmt, 0.5, "Rs.\u00a00.50");
1240 // expect2(fmt, -1.0, "-Re.\u00a01.00");
1241 // expect2(fmt, -10.0, "-Rs.\u00a010.00");
1244 public void TestCurrencyKeyword() {
1245 ULocale locale = new ULocale("th_TH@currency=QQQ");
1246 NumberFormat format = NumberFormat.getCurrencyInstance(locale);
1247 String result = format.format(12.34f);
1248 if (!"QQQ12.34".equals(result)) {
1249 errln("got unexpected currency: " + result);
1254 * Test alternate numbering systems
1256 public void TestNumberingSystems() {
1258 ULocale loc1 = new ULocale("en_US@numbers=thai");
1259 ULocale loc2 = new ULocale("en_US@numbers=hebr");
1260 ULocale loc3 = new ULocale("en_US@numbers=arabext");
1261 ULocale loc4 = new ULocale("hi_IN@numbers=foobar");
1263 NumberFormat fmt1 = NumberFormat.getInstance(loc1);
1264 NumberFormat fmt2 = NumberFormat.getInstance(loc2);
1265 NumberFormat fmt3 = NumberFormat.getInstance(loc3);
1266 NumberFormat fmt4 = NumberFormat.getInstance(loc4);
1268 expect2(fmt1,1234.567,"\u0e51,\u0e52\u0e53\u0e54.\u0e55\u0e56\u0e57");
1269 expect3(fmt2,5678.0,"\u05d4\u05f3\u05ea\u05e8\u05e2\u05f4\u05d7");
1270 expect2(fmt3,1234.567,"\u06f1,\u06f2\u06f3\u06f4.\u06f5\u06f6\u06f7");
1271 expect2(fmt4,1234.567,"\u0967,\u0968\u0969\u096a.\u096b\u096c\u096d");
1275 public void TestThreadedFormat() {
1277 class FormatTask implements Runnable {
1283 FormatTask(DecimalFormat fmt, int index) {
1285 this.buf = new StringBuffer();
1286 this.inc = (index & 0x1) == 0;
1287 this.num = inc ? 0 : 10000;
1292 while (num < 10000) {
1293 buf.append(fmt.format(num) + "\n");
1298 buf.append(fmt.format(num) + "\n");
1305 return buf.toString();
1309 DecimalFormat fmt = new DecimalFormat("0.####");
1310 FormatTask[] tasks = new FormatTask[8];
1311 for (int i = 0; i < tasks.length; ++i) {
1312 tasks[i] = new FormatTask(fmt, i);
1315 TestUtil.runUntilDone(tasks);
1317 for (int i = 2; i < tasks.length; i++) {
1318 String str1 = tasks[i].result();
1319 String str2 = tasks[i-2].result();
1320 if (!str1.equals(str2)) {
1321 System.out.println("mismatch at " + i);
1322 System.out.println(str1);
1323 System.out.println(str2);
1324 errln("decimal format thread mismatch");
1332 public void TestPerMill() {
1333 DecimalFormat fmt = new DecimalFormat("###.###\u2030");
1334 assertEquals("0.4857 x ###.###\u2030",
1335 "485.7\u2030", fmt.format(0.4857));
1337 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.ENGLISH);
1338 sym.setPerMill('m');
1339 DecimalFormat fmt2 = new DecimalFormat("", sym);
1340 fmt2.applyLocalizedPattern("###.###m");
1341 assertEquals("0.4857 x ###.###m",
1342 "485.7m", fmt2.format(0.4857));
1345 public void TestIllegalPatterns() {
1347 // Prefix with "-:" for illegal patterns
1348 // Prefix with "+:" for legal patterns
1350 // Unquoted special characters in the suffix are illegal
1354 for (int i=0; i<DATA.length; ++i) {
1356 boolean valid = pat.charAt(0) == '+';
1357 pat = pat.substring(2);
1360 // locale doesn't matter here
1361 new DecimalFormat(pat);
1362 } catch (IllegalArgumentException e1) {
1364 } catch (IndexOutOfBoundsException e1) {
1367 String msg = (e==null) ? "success" : e.getMessage();
1368 if ((e==null) == valid) {
1369 logln("Ok: pattern \"" + pat + "\": " + msg);
1371 errln("FAIL: pattern \"" + pat + "\" should have " +
1372 (valid?"succeeded":"failed") + "; got " + msg);
1378 * Parse a CurrencyAmount using the given NumberFormat, with
1379 * the 'delim' character separating the number and the currency.
1381 private static CurrencyAmount parseCurrencyAmount(String str, NumberFormat fmt,
1383 throws ParseException {
1384 int i = str.indexOf(delim);
1385 return new CurrencyAmount(fmt.parse(str.substring(0,i)),
1386 Currency.getInstance(str.substring(i+1)));
1390 * Return an integer representing the next token from this
1391 * iterator. The integer will be an index into the given list, or
1392 * -1 if there are no more tokens, or -2 if the token is not on
1395 private static int keywordIndex(String tok) {
1396 for (int i=0; i<KEYWORDS.length; ++i) {
1397 if (tok.equals(KEYWORDS[i])) {
1404 private static final String KEYWORDS[] = {
1405 /*0*/ "ref=", // <reference pattern to parse numbers>
1406 /*1*/ "loc=", // <locale for formats>
1407 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
1408 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
1409 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
1410 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
1411 /*6*/ "perr:", // <pattern or '-'> <invalid string>
1412 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1413 /*8*/ "fpc:", // <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1414 /*9*/ "strict=", // true or false
1417 public void TestCases() {
1418 String caseFileName = "NumberFormatTestCases.txt";
1419 java.io.InputStream is = NumberFormatTest.class.getResourceAsStream(caseFileName);
1421 ResourceReader reader = new ResourceReader(is, caseFileName, "utf-8");
1422 TokenIterator tokens = new TokenIterator(reader);
1424 Locale loc = new Locale("en", "US", "");
1425 DecimalFormat ref = null, fmt = null;
1426 MeasureFormat mfmt = null;
1427 String pat = null, str = null, mloc = null;
1428 boolean strict = false;
1432 String tok = tokens.next();
1436 String where = "(" + tokens.getLineNumber() + ") ";
1437 int cmd = keywordIndex(tok);
1440 // ref= <reference pattern>
1441 ref = new DecimalFormat(tokens.next(),
1442 new DecimalFormatSymbols(Locale.US));
1443 ref.setParseStrict(strict);
1444 logln("Setting reference pattern to:\t" + ref);
1448 loc = LocaleUtility.getLocaleFromName(tokens.next());
1449 pat = ((DecimalFormat) NumberFormat.getInstance(loc)).toPattern();
1450 logln("Setting locale to:\t" + loc + ", \tand pattern to:\t" + pat);
1456 tok = tokens.next();
1457 if (!tok.equals("-")) {
1461 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc));
1462 fmt.setParseStrict(strict);
1463 } catch (IllegalArgumentException iae) {
1464 errln(where + "Pattern \"" + pat + '"');
1465 iae.printStackTrace();
1466 tokens.next(); // consume remaining tokens
1468 if (cmd == 3) tokens.next();
1473 if (cmd == 2 || cmd == 3 || cmd == 4) {
1474 // f: <pattern or '-'> <number> <exp. string>
1475 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
1476 // rt: <pattern or '-'> <number> <string>
1477 String num = tokens.next();
1478 str = tokens.next();
1479 Number n = (Number) ref.parse(num);
1480 assertEquals(where + '"' + pat + "\".format(" + num + ")",
1481 str, fmt.format(n));
1482 if (cmd == 3) { // fp:
1483 n = (Number) ref.parse(tokens.next());
1485 if (cmd != 2) { // != f:
1486 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1490 // p: <pattern or '-'> <string to parse> <exp. number>
1492 str = tokens.next();
1493 String expstr = tokens.next();
1494 Number parsed = fmt.parse(str);
1495 Number exp = (Number) ref.parse(expstr);
1496 assertEquals(where + '"' + pat + "\".parse(\"" + str + "\")",
1499 } catch (ParseException e) {
1500 errln(where + '"' + pat + "\".parse(\"" + str +
1501 "\") threw an exception");
1502 e.printStackTrace();
1506 // perr: <pattern or '-'> <invalid string>
1507 errln("Under construction");
1510 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
1511 String testpat = tokens.next();
1512 String exppat = tokens.next();
1513 boolean err = exppat.equals("err");
1514 if (testpat.equals("-")) {
1516 errln("Invalid command \"pat: - err\" at " + tokens.describePosition());
1521 if (exppat.equals("-")) exppat = testpat;
1523 DecimalFormat f = null;
1524 if (testpat == pat) { // [sic]
1527 f = new DecimalFormat(testpat);
1528 f.setParseStrict(strict);
1531 errln(where + "Invalid pattern \"" + testpat +
1534 assertEquals(where + '"' + testpat + "\".toPattern()",
1535 exppat, f.toPattern());
1537 } catch (IllegalArgumentException iae2) {
1539 logln("Ok: " + where + "Invalid pattern \"" + testpat +
1540 "\" threw an exception");
1542 errln(where + "Valid pattern \"" + testpat +
1543 "\" threw an exception");
1544 iae2.printStackTrace();
1549 tok = tokens.next();
1550 if (!tok.equals("-")) {
1552 ULocale l = new ULocale(mloc);
1554 mfmt = MeasureFormat.getCurrencyFormat(l);
1555 } catch (IllegalArgumentException iae) {
1556 errln(where + "Loc \"" + tok + '"');
1557 iae.printStackTrace();
1558 tokens.next(); // consume remaining tokens
1566 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1567 String currAmt = tokens.next();
1568 str = tokens.next();
1569 CurrencyAmount n = parseCurrencyAmount(currAmt, ref, '/');
1570 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
1571 str, mfmt.format(n));
1572 n = parseCurrencyAmount(tokens.next(), ref, '/');
1573 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
1574 n, (CurrencyAmount) mfmt.parseObject(str));
1575 } catch (ParseException e) {
1576 errln(where + '"' + pat + "\".parse(\"" + str +
1577 "\") threw an exception");
1578 e.printStackTrace();
1581 case 9: // strict= true or false
1582 strict = "true".equalsIgnoreCase(tokens.next());
1583 logln("Setting strict to:\t" + strict);
1586 errln("Unknown command \"" + tok + "\" at " + tokens.describePosition());
1590 } catch (java.io.IOException e) {
1591 //#if defined(FOUNDATION10) || defined(J2SE13)
1592 //## throw new RuntimeException(e.getMessage());
1594 throw new RuntimeException(e);
1599 public void TestRounding() {
1600 DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
1601 if (false) { // for debugging specific value
1602 nf.setRoundingMode(BigDecimal.ROUND_HALF_UP);
1603 checkRounding(nf, new BigDecimal("300.0300000000"), 0, new BigDecimal("0.020000000"));
1606 int[] roundingIncrements = {1, 2, 5, 20, 50, 100};
1607 int[] testValues = {0, 300};
1608 for (int j = 0; j < testValues.length; ++j) {
1609 for (int mode = BigDecimal.ROUND_UP; mode < BigDecimal.ROUND_HALF_EVEN; ++mode) {
1610 nf.setRoundingMode(mode);
1611 for (int increment = 0; increment < roundingIncrements.length; ++increment) {
1612 BigDecimal base = new BigDecimal(testValues[j]);
1613 BigDecimal rInc = new BigDecimal(roundingIncrements[increment]);
1614 checkRounding(nf, base, 20, rInc);
1615 rInc = new BigDecimal("1.000000000").divide(rInc);
1616 checkRounding(nf, base, 20, rInc);
1622 void checkRounding(DecimalFormat nf, BigDecimal base, int iterations, BigDecimal increment) {
1623 //#if defined(FOUNDATION10)
1624 //## nf.setRoundingIncrement(increment);
1626 nf.setRoundingIncrement(increment.toBigDecimal());
1628 BigDecimal lastParsed = new BigDecimal(Integer.MIN_VALUE); // used to make sure that rounding is monotonic
1629 for (int i = -iterations; i <= iterations; ++i) {
1630 BigDecimal iValue = base.add(increment.multiply(new BigDecimal(i)).movePointLeft(1));
1631 BigDecimal smallIncrement = new BigDecimal("0.00000001");
1632 if (iValue.signum() != 0) {
1633 smallIncrement.multiply(iValue); // scale unless zero
1635 // we not only test the value, but some values in a small range around it.
1636 lastParsed = checkRound(nf, iValue.subtract(smallIncrement), lastParsed);
1637 lastParsed = checkRound(nf, iValue, lastParsed);
1638 lastParsed = checkRound(nf, iValue.add(smallIncrement), lastParsed);
1642 private BigDecimal checkRound(DecimalFormat nf, BigDecimal iValue, BigDecimal lastParsed) {
1643 String formatedBigDecimal = nf.format(iValue);
1644 String formattedDouble = nf.format(iValue.doubleValue());
1645 if (!equalButForTrailingZeros(formatedBigDecimal, formattedDouble)) {
1646 errln("Failure at: " + iValue + " (" + iValue.doubleValue() + ")"
1647 + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1648 + ",\tRounding-increment: " + nf.getRoundingIncrement()
1649 + ",\tdouble: " + formattedDouble
1650 + ",\tBigDecimal: " + formatedBigDecimal);
1652 logln("Value: " + iValue
1653 + ",\tRounding-mode: " + roundingModeNames[nf.getRoundingMode()]
1654 + ",\tRounding-increment: " + nf.getRoundingIncrement()
1655 + ",\tdouble: " + formattedDouble
1656 + ",\tBigDecimal: " + formatedBigDecimal);
1659 // Number should have compareTo(...)
1660 BigDecimal parsed = toBigDecimal(nf.parse(formatedBigDecimal));
1661 if (lastParsed.compareTo(parsed) > 0) {
1662 errln("Rounding wrong direction!: " + lastParsed + " > " + parsed);
1664 lastParsed = parsed;
1665 } catch (ParseException e) {
1666 errln("Parse Failure with: " + formatedBigDecimal);
1671 static BigDecimal toBigDecimal(Number number) {
1672 return number instanceof BigDecimal ? (BigDecimal) number
1673 : number instanceof BigInteger ? new BigDecimal((BigInteger)number)
1674 //#if defined(FOUNDATION10)
1676 : number instanceof java.math.BigDecimal ? new BigDecimal((java.math.BigDecimal)number)
1678 : number instanceof Double ? new BigDecimal(number.doubleValue())
1679 : number instanceof Float ? new BigDecimal(number.floatValue())
1680 : new BigDecimal(number.longValue());
1683 static String[] roundingModeNames = {
1684 "ROUND_UP", "ROUND_DOWN", "ROUND_CEILING", "ROUND_FLOOR",
1685 "ROUND_HALF_UP", "ROUND_HALF_DOWN", "ROUND_HALF_EVEN",
1689 private static boolean equalButForTrailingZeros(String formatted1, String formatted2) {
1690 if (formatted1.length() == formatted2.length()) return formatted1.equals(formatted2);
1691 return stripFinalZeros(formatted1).equals(stripFinalZeros(formatted2));
1694 private static String stripFinalZeros(String formatted) {
1695 int len1 = formatted.length();
1697 while (len1 > 0 && ((ch = formatted.charAt(len1-1)) == '0' || ch == '.')) --len1;
1698 return formatted.substring(0,len1);
1701 //------------------------------------------------------------------
1703 //------------------------------------------------------------------
1705 // Format-Parse test
1706 public void expect2(NumberFormat fmt, Number n, String exp) {
1707 // Don't round-trip format test, since we explicitly do it
1708 expect(fmt, n, exp, false);
1709 expect(fmt, exp, n);
1711 // Format-Parse test
1712 public void expect3(NumberFormat fmt, Number n, String exp) {
1713 // Don't round-trip format test, since we explicitly do it
1714 expect_rbnf(fmt, n, exp, false);
1715 expect_rbnf(fmt, exp, n);
1718 // Format-Parse test (convenience)
1719 public void expect2(NumberFormat fmt, double n, String exp) {
1720 expect2(fmt, new Double(n), exp);
1722 // Format-Parse test (convenience)
1723 public void expect3(NumberFormat fmt, double n, String exp) {
1724 expect3(fmt, new Double(n), exp);
1727 // Format-Parse test (convenience)
1728 public void expect2(NumberFormat fmt, long n, String exp) {
1729 expect2(fmt, new Long(n), exp);
1731 // Format-Parse test (convenience)
1732 public void expect3(NumberFormat fmt, long n, String exp) {
1733 expect3(fmt, new Long(n), exp);
1737 public void expect(NumberFormat fmt, Number n, String exp, boolean rt) {
1738 StringBuffer saw = new StringBuffer();
1739 FieldPosition pos = new FieldPosition(0);
1740 fmt.format(n, saw, pos);
1741 String pat = ((DecimalFormat)fmt).toPattern();
1742 if (saw.toString().equals(exp)) {
1743 logln("Ok " + n + " x " +
1746 // We should be able to round-trip the formatted string =>
1747 // number => string (but not the other way around: number
1748 // => string => number2, might have number2 != number):
1751 Number n2 = fmt.parse(exp);
1752 StringBuffer saw2 = new StringBuffer();
1753 fmt.format(n2, saw2, pos);
1754 if (!saw2.toString().equals(exp)) {
1755 errln("FAIL \"" + exp + "\" => " + n2 +
1756 " => \"" + saw2 + '"');
1758 } catch (ParseException e) {
1759 errln(e.getMessage());
1764 errln("FAIL " + n + " x " +
1766 saw + "\", expected \"" + exp + "\"");
1770 public void expect_rbnf(NumberFormat fmt, Number n, String exp, boolean rt) {
1771 StringBuffer saw = new StringBuffer();
1772 FieldPosition pos = new FieldPosition(0);
1773 fmt.format(n, saw, pos);
1774 if (saw.toString().equals(exp)) {
1775 logln("Ok " + n + " = \"" +
1777 // We should be able to round-trip the formatted string =>
1778 // number => string (but not the other way around: number
1779 // => string => number2, might have number2 != number):
1782 Number n2 = fmt.parse(exp);
1783 StringBuffer saw2 = new StringBuffer();
1784 fmt.format(n2, saw2, pos);
1785 if (!saw2.toString().equals(exp)) {
1786 errln("FAIL \"" + exp + "\" => " + n2 +
1787 " => \"" + saw2 + '"');
1789 } catch (ParseException e) {
1790 errln(e.getMessage());
1795 errln("FAIL " + n + " = \"" +
1796 saw + "\", expected \"" + exp + "\"");
1800 // Format test (convenience)
1801 public void expect(NumberFormat fmt, Number n, String exp) {
1802 expect(fmt, n, exp, true);
1805 // Format test (convenience)
1806 public void expect(NumberFormat fmt, double n, String exp) {
1807 expect(fmt, new Double(n), exp);
1810 // Format test (convenience)
1811 public void expect(NumberFormat fmt, long n, String exp) {
1812 expect(fmt, new Long(n), exp);
1816 public void expect(NumberFormat fmt, String str, Number n) {
1819 num = (Number) fmt.parse(str);
1820 } catch (ParseException e) {
1821 errln(e.getMessage());
1824 String pat = ((DecimalFormat)fmt).toPattern();
1825 // A little tricky here -- make sure Double(12345.0) and
1826 // Long(12345) match.
1827 if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1828 logln("Ok \"" + str + "\" x " +
1832 errln("FAIL \"" + str + "\" x " +
1834 num + ", expected " + n);
1839 public void expect_rbnf(NumberFormat fmt, String str, Number n) {
1842 num = (Number) fmt.parse(str);
1843 } catch (ParseException e) {
1844 errln(e.getMessage());
1847 // A little tricky here -- make sure Double(12345.0) and
1848 // Long(12345) match.
1849 if (num.equals(n) || num.doubleValue() == n.doubleValue()) {
1850 logln("Ok \"" + str + " = " +
1853 errln("FAIL \"" + str + " = " +
1854 num + ", expected " + n);
1858 // Parse test (convenience)
1859 public void expect(NumberFormat fmt, String str, double n) {
1860 expect(fmt, str, new Double(n));
1863 // Parse test (convenience)
1864 public void expect(NumberFormat fmt, String str, long n) {
1865 expect(fmt, str, new Long(n));
1868 private void expectCurrency(NumberFormat nf, Currency curr,
1869 double value, String string) {
1870 DecimalFormat fmt = (DecimalFormat) nf;
1872 fmt.setCurrency(curr);
1874 String s = fmt.format(value).replace('\u00A0', ' ');
1876 if (s.equals(string)) {
1877 logln("Ok: " + value + " x " + curr + " => " + s);
1879 errln("FAIL: " + value + " x " + curr + " => " + s +
1880 ", expected " + string);
1884 public void expectPad(DecimalFormat fmt, String pat, int pos) {
1885 expectPad(fmt, pat, pos, 0, (char)0);
1888 public void expectPad(DecimalFormat fmt, final String pat, int pos, int width, final char pad) {
1889 int apos = 0, awidth = 0;
1892 fmt.applyPattern(pat);
1893 apos = fmt.getPadPosition();
1894 awidth = fmt.getFormatWidth();
1895 apadStr = fmt.getPadCharacter();
1896 } catch (Exception e) {
1902 if (apos == pos && awidth == width && apadStr == pad) {
1903 logln("Ok \"" + pat + "\" pos="
1904 + apos + ((pos == -1) ? "" : " width=" + awidth + " pad=" + apadStr));
1906 errln("FAIL \"" + pat + "\" pos=" + apos + " width="
1907 + awidth + " pad=" + apadStr + ", expected "
1908 + pos + " " + width + " " + pad);
1912 public void expectPat(DecimalFormat fmt, final String exp) {
1913 String pat = fmt.toPattern();
1914 if (pat.equals(exp)) {
1915 logln("Ok \"" + pat + "\"");
1917 errln("FAIL \"" + pat + "\", expected \"" + exp + "\"");
1921 public void TestJB3832(){
1922 ULocale locale = new ULocale("pt_PT@currency=PTE");
1923 NumberFormat format = NumberFormat.getCurrencyInstance(locale);
1924 Currency curr = Currency.getInstance(locale);
1925 logln("\nName of the currency is: " + curr.getName(locale, Currency.LONG_NAME, new boolean[] {false}));
1926 CurrencyAmount cAmt = new CurrencyAmount(1150.50, curr);
1927 logln("CurrencyAmount object's hashCode is: " + cAmt.hashCode()); //cover hashCode
1928 String str = format.format(cAmt);
1929 String expected = "1,150$50\u00a0Esc.";
1930 if(!expected.equals(str)){
1931 errln("Did not get the expected output Expected: "+expected+" Got: "+ str);
1935 public void TestStrictParse() {
1937 "0", // single zero before end of text is not leading
1938 "0 ", // single zero at end of number is not leading
1939 "0.", // single zero before period (or decimal, it's ambiguous) is not leading
1940 "0,", // single zero before comma (not group separator) is not leading
1941 "0.0", // single zero before decimal followed by digit is not leading
1942 "0. ", // same as above before period (or decimal) is not leading
1943 "0.100,5", // comma stops parse of decimal (no grouping)
1944 ".00", // leading decimal is ok, even with zeros
1945 "1234567", // group separators are not required
1946 "12345, ", // comma not followed by digit is not a group separator, but end of number
1947 "1,234, ", // if group separator is present, group sizes must be appropriate
1948 "1,234,567", // ...secondary too
1949 "0E", // an exponnent not followed by zero or digits is not an exponent
1952 "00", // leading zero before zero
1953 "012", // leading zero before digit
1954 "0,456", // leading zero before group separator
1955 "1,2", // wrong number of digits after group separator
1956 ",0", // leading group separator before zero
1957 ",1", // leading group separator before digit
1958 ",.02", // leading group separator before decimal
1959 "1,.02", // group separator before decimal
1960 "1,,200", // multiple group separators
1961 "1,45", // wrong number of digits in primary group
1962 "1,45 that", // wrong number of digits in primary group
1963 "1,45.34", // wrong number of digits in primary group
1964 "1234,567", // wrong number of digits in secondary group
1965 "12,34,567", // wrong number of digits in secondary group
1966 "1,23,456,7890", // wrong number of digits in primary and secondary groups
1969 DecimalFormat nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
1970 runStrictParseBatch(nf, pass, fail);
1972 String[] scientificPass = {
1973 "0E2", // single zero before exponent is ok
1974 "1234E2", // any number of digits before exponent is ok
1975 "1,234E", // an exponent string not followed by zero or digits is not an exponent
1977 String[] scientificFail = {
1978 "00E2", // double zeros fail
1979 "1,234E2", // group separators with exponent fail
1982 nf = (DecimalFormat) NumberFormat.getInstance(Locale.ENGLISH);
1983 runStrictParseBatch(nf, scientificPass, scientificFail);
1985 String[] mixedPass = {
1991 String[] mixedFail = {
1998 nf = new DecimalFormat("#,##,##0.#");
1999 runStrictParseBatch(nf, mixedPass, mixedFail);
2002 void runStrictParseBatch(DecimalFormat nf, String[] pass, String[] fail) {
2003 nf.setParseStrict(false);
2004 runStrictParseTests("should pass", nf, pass, true);
2005 runStrictParseTests("should also pass", nf, fail, true);
2006 nf.setParseStrict(true);
2007 runStrictParseTests("should still pass", nf, pass, true);
2008 runStrictParseTests("should fail", nf, fail, false);
2011 void runStrictParseTests(String msg, DecimalFormat nf, String[] tests, boolean pass) {
2013 logln("pattern: '" + nf.toPattern() + "'");
2015 for (int i = 0; i < tests.length; ++i) {
2016 String str = tests[i];
2017 ParsePosition pp = new ParsePosition(0);
2018 Number n = nf.parse(str, pp);
2019 String formatted = n != null ? nf.format(n) : "null";
2020 String err = pp.getErrorIndex() == -1 ? "" : "(error at " + pp.getErrorIndex() + ")";
2021 if ((err.length() == 0) != pass) {
2022 errln("'" + str + "' parsed '" +
2023 str.substring(0, pp.getIndex()) +
2024 "' returned " + n + " formats to '" +
2025 formatted + "' " + err);
2027 if (err.length() > 0) {
2028 err = "got expected " + err;
2030 logln("'" + str + "' parsed '" +
2031 str.substring(0, pp.getIndex()) +
2032 "' returned " + n + " formats to '" +
2033 formatted + "' " + err);
2037 public void TestJB5251(){
2038 //save default locale
2039 ULocale defaultLocale = ULocale.getDefault();
2040 ULocale.setDefault(new ULocale("qr_QR"));
2042 NumberFormat.getInstance();
2044 catch (Exception e) {
2045 errln("Numberformat threw exception for non-existent locale. It should use the default.");
2047 //reset default locale
2048 ULocale.setDefault(defaultLocale);
2051 public void TestParseReturnType() {
2052 String[] defaultNonBigDecimals = {
2056 "12345678901234567890" // BigInteger
2059 String[] doubles = {
2062 "\u221E" // Infinity
2065 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2066 DecimalFormat nf = new DecimalFormat("#.#", sym);
2068 if (nf.isParseBigDecimal()) {
2069 errln("FAIL: isParseDecimal() must return false by default");
2072 // isParseBigDecimal() is false
2073 for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2075 Number n = nf.parse(defaultNonBigDecimals[i]);
2076 if (n instanceof BigDecimal) {
2077 errln("FAIL: parse returns BigDecimal instance");
2079 } catch (ParseException e) {
2080 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2083 // parse results for doubls must be always Double
2084 for (int i = 0; i < doubles.length; i++) {
2086 Number n = nf.parse(doubles[i]);
2087 if (!(n instanceof Double)) {
2088 errln("FAIL: parse does not return Double instance");
2090 } catch (ParseException e) {
2091 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2095 // force this DecimalFormat to return BigDecimal
2096 nf.setParseBigDecimal(true);
2097 if (!nf.isParseBigDecimal()) {
2098 errln("FAIL: isParseBigDecimal() must return true");
2101 // isParseBigDecimal() is true
2102 for (int i = 0; i < defaultNonBigDecimals.length; i++) {
2104 Number n = nf.parse(defaultNonBigDecimals[i]);
2105 if (!(n instanceof BigDecimal)) {
2106 errln("FAIL: parse does not return BigDecimal instance");
2108 } catch (ParseException e) {
2109 errln("parse of '" + defaultNonBigDecimals[i] + "' threw exception: " + e);
2112 // parse results for doubls must be always Double
2113 for (int i = 0; i < doubles.length; i++) {
2115 Number n = nf.parse(doubles[i]);
2116 if (!(n instanceof Double)) {
2117 errln("FAIL: parse does not return Double instance");
2119 } catch (ParseException e) {
2120 errln("parse of '" + doubles[i] + "' threw exception: " + e);
2125 public void TestNonpositiveMultiplier() {
2126 DecimalFormat df = new DecimalFormat("0");
2128 // test zero multiplier
2131 df.setMultiplier(0);
2134 errln("DecimalFormat.setMultiplier(0) did not throw an IllegalArgumentException");
2135 } catch (IllegalArgumentException ex) {
2139 // test negative multiplier
2142 df.setMultiplier(-1);
2144 if (df.getMultiplier() != -1) {
2145 errln("DecimalFormat.setMultiplier(-1) did not change the multiplier to -1");
2150 } catch (IllegalArgumentException ex) {
2152 errln("DecimalFormat.setMultiplier(-1) threw an IllegalArgumentException");
2156 expect(df, "1122.123", -1122.123);
2157 expect(df, "-1122.123", 1122.123);
2158 expect(df, "1.2", -1.2);
2159 expect(df, "-1.2", 1.2);
2161 expect2(df, Long.MAX_VALUE, BigInteger.valueOf(Long.MAX_VALUE).negate().toString());
2162 expect2(df, Long.MIN_VALUE, BigInteger.valueOf(Long.MIN_VALUE).negate().toString());
2163 expect2(df, Long.MAX_VALUE / 2, BigInteger.valueOf(Long.MAX_VALUE / 2).negate().toString());
2164 expect2(df, Long.MIN_VALUE / 2, BigInteger.valueOf(Long.MIN_VALUE / 2).negate().toString());
2166 expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2167 expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2169 //#if defined(FOUNDATION10)
2171 expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2172 expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2176 public void TestJB5358() {
2177 int numThreads = 10;
2178 String numstr = "12345";
2179 double expected = 12345;
2180 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
2181 DecimalFormat fmt = new DecimalFormat("#.#", sym);
2182 ArrayList errors = new ArrayList();
2184 ParseThreadJB5358[] threads = new ParseThreadJB5358[numThreads];
2185 for (int i = 0; i < numThreads; i++) {
2186 threads[i] = new ParseThreadJB5358((DecimalFormat)fmt.clone(), numstr, expected, errors);
2189 for (int i = 0; i < numThreads; i++) {
2192 } catch (InterruptedException ie) {
2193 ie.printStackTrace();
2196 if (errors.size() != 0) {
2197 StringBuffer errBuf = new StringBuffer();
2198 for (int i = 0; i < errors.size(); i++) {
2199 errBuf.append((String)errors.get(i));
2200 errBuf.append("\n");
2202 errln("FAIL: " + errBuf);
2206 static private class ParseThreadJB5358 extends Thread {
2207 private DecimalFormat decfmt;
2208 private String numstr;
2209 private double expect;
2210 private ArrayList errors;
2212 public ParseThreadJB5358(DecimalFormat decfmt, String numstr, double expect, ArrayList errors) {
2213 this.decfmt = decfmt;
2214 this.numstr = numstr;
2215 this.expect = expect;
2216 this.errors = errors;
2220 for (int i = 0; i < 10000; i++) {
2222 Number n = decfmt.parse(numstr);
2223 if (n.doubleValue() != expect) {
2224 synchronized(errors) {
2225 errors.add(new String("Bad parse result - expected:" + expect + " actual:" + n.doubleValue()));
2228 } catch (Throwable t) {
2229 synchronized(errors) {
2230 errors.add(new String(t.getClass().getName() + " - " + t.getMessage()));
2237 public void TestSetCurrency() {
2238 DecimalFormatSymbols decf1 = DecimalFormatSymbols.getInstance(ULocale.US);
2239 DecimalFormatSymbols decf2 = DecimalFormatSymbols.getInstance(ULocale.US);
2240 decf2.setCurrencySymbol("UKD");
2241 DecimalFormat format1 = new DecimalFormat("000.000", decf1);
2242 DecimalFormat format2 = new DecimalFormat("000.000", decf2);
2243 Currency euro = Currency.getInstance("EUR");
2244 format1.setCurrency(euro);
2245 format2.setCurrency(euro);
2246 assertEquals("Reset with currency symbol", format1, format2);