1 /*****************************************************************************************
\r
3 * Copyright (C) 1996-2009, International Business Machines
\r
4 * Corporation and others. All Rights Reserved.
\r
8 * Port From: JDK 1.4b1 : java.text.Format.NumberRegression
\r
9 * Source File: java/text/format/NumberRegression.java
\r
13 * @test 1.49 01/05/21
\r
14 * @bug 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014
\r
15 * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245
\r
16 * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713
\r
17 * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840
\r
18 * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198
\r
19 * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742
\r
20 * 4217661 4243011 4243108 4330377 4233840
\r
21 * @summary Regression tests for NumberFormat and associated classes
\r
24 package com.ibm.icu.dev.test.format;
\r
26 import java.io.ByteArrayInputStream;
\r
27 import java.io.ByteArrayOutputStream;
\r
28 import java.io.IOException;
\r
29 import java.io.InvalidObjectException;
\r
30 import java.io.ObjectInputStream;
\r
31 import java.io.ObjectOutputStream;
\r
32 import java.io.Serializable;
\r
33 import java.math.BigInteger;
\r
34 import java.text.FieldPosition;
\r
35 import java.text.ParseException;
\r
36 import java.text.ParsePosition;
\r
37 import java.util.Date;
\r
38 import java.util.Locale;
\r
40 import com.ibm.icu.impl.ICUResourceBundle;
\r
41 import com.ibm.icu.text.DateFormat;
\r
42 import com.ibm.icu.text.DecimalFormat;
\r
43 import com.ibm.icu.text.DecimalFormatSymbols;
\r
44 import com.ibm.icu.text.NumberFormat;
\r
45 import com.ibm.icu.util.GregorianCalendar;
\r
46 import com.ibm.icu.util.ULocale;
\r
47 import com.ibm.icu.util.UResourceBundle;
\r
48 import com.ibm.icu.util.VersionInfo;
\r
50 public class NumberRegression extends com.ibm.icu.dev.test.TestFmwk {
\r
52 public static void main(String[] args) throws Exception {
\r
53 new NumberRegression().run(args);
\r
56 private static final char EURO = '\u20ac';
\r
59 * NumberFormat.equals comparing with null should always return false.
\r
61 public void Test4075713(){
\r
64 MyNumberFormatTest tmp = new MyNumberFormatTest();
\r
65 if (!tmp.equals(null))
\r
66 logln("NumberFormat.equals passed");
\r
67 } catch (NullPointerException e) {
\r
68 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
\r
73 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
\r
74 * flag is different.
\r
76 public void Test4074620() {
\r
78 MyNumberFormatTest nf1 = new MyNumberFormatTest();
\r
79 MyNumberFormatTest nf2 = new MyNumberFormatTest();
\r
81 nf1.setGroupingUsed(false);
\r
82 nf2.setGroupingUsed(true);
\r
84 if (nf1.equals(nf2)) errln("Test for bug 4074620 failed");
\r
85 else logln("Test for bug 4074620 passed.");
\r
91 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
\r
94 public void Test4088161 (){
\r
95 DecimalFormat df = new DecimalFormat();
\r
97 df.setMinimumFractionDigits(0);
\r
98 df.setMaximumFractionDigits(16);
\r
99 StringBuffer sBuf1 = new StringBuffer("");
\r
100 FieldPosition fp1 = new FieldPosition(0);
\r
102 logln("maxFractionDigits = " + df.getMaximumFractionDigits());
\r
103 logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'");
\r
104 df.setMaximumFractionDigits(17);
\r
105 StringBuffer sBuf2 = new StringBuffer("");
\r
106 FieldPosition fp2 = new FieldPosition(0);
\r
107 logln("maxFractionDigits = " + df.getMaximumFractionDigits());
\r
108 df.format(d, sBuf2, fp2);
\r
109 if (!sBuf2.toString().equals("100"))
\r
110 errln(" format(d) = '" + sBuf2 + "'");
\r
113 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
\r
114 * DecimalFormat(String, DecimalFormatSymbols).
\r
116 public void Test4087245 (){
\r
117 DecimalFormatSymbols symbols = new DecimalFormatSymbols();
\r
118 DecimalFormat df = new DecimalFormat("#,##0.0", symbols);
\r
120 StringBuffer buf1 = new StringBuffer();
\r
121 StringBuffer buf2 = new StringBuffer();
\r
122 logln("format(" + n + ") = " +
\r
123 df.format(n, buf1, new FieldPosition(0)));
\r
124 symbols.setDecimalSeparator('p'); // change value of field
\r
125 logln("format(" + n + ") = " +
\r
126 df.format(n, buf2, new FieldPosition(0)));
\r
127 if (!buf1.toString().equals(buf2.toString()))
\r
128 errln("Test for bug 4087245 failed");
\r
131 * DecimalFormat.format() incorrectly formats 0.0
\r
133 public void Test4087535 ()
\r
135 DecimalFormat df = new DecimalFormat();
\r
136 df.setMinimumIntegerDigits(0);
\r
139 String buffer = new String();
\r
140 buffer = df.format(n);
\r
141 if (buffer.length() == 0)
\r
142 errln(n + ": '" + buffer + "'");
\r
144 buffer = df.format(n);
\r
145 if (buffer.length() == 0)
\r
146 errln(n + ": '" + buffer + "'");
\r
150 * DecimalFormat.format fails when groupingSize is set to 0.
\r
152 public void Test4088503 (){
\r
153 DecimalFormat df = new DecimalFormat();
\r
154 df.setGroupingSize(0);
\r
155 StringBuffer sBuf = new StringBuffer("");
\r
156 FieldPosition fp = new FieldPosition(0);
\r
158 logln(df.format(123, sBuf, fp).toString());
\r
159 } catch (Exception foo) {
\r
160 errln("Test for bug 4088503 failed.");
\r
165 * NumberFormat.getCurrencyInstance is wrong.
\r
167 public void Test4066646 () {
\r
168 //float returnfloat = 0.0f; //The variable is never used
\r
169 assignFloatValue(2.04f);
\r
170 assignFloatValue(2.03f);
\r
171 assignFloatValue(2.02f);
\r
172 assignFloatValue(0.0f);
\r
175 public float assignFloatValue(float returnfloat)
\r
177 logln(" VALUE " + returnfloat);
\r
178 NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US);
\r
179 nfcommon.setGroupingUsed(false);
\r
181 String stringValue = nfcommon.format(returnfloat).substring(1);
\r
182 if (Float.valueOf(stringValue).floatValue() != returnfloat)
\r
183 errln(" DISPLAYVALUE " + stringValue);
\r
184 return returnfloat;
\r
185 } // End Of assignFloatValue()
\r
188 * DecimalFormat throws exception when parsing "0"
\r
190 public void Test4059870() {
\r
191 DecimalFormat format = new DecimalFormat("00");
\r
193 logln(format.parse("0").toString());
\r
194 } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); }
\r
197 * DecimalFormatSymbol.equals should always return false when
\r
198 * comparing with null.
\r
201 public void Test4083018 (){
\r
202 DecimalFormatSymbols dfs = new DecimalFormatSymbols();
\r
204 if (!dfs.equals(null))
\r
205 logln("Test Passed!");
\r
206 } catch (Exception foo) {
\r
207 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
\r
211 * DecimalFormat does not round up correctly.
\r
213 public void Test4071492 (){
\r
214 double x = 0.00159999;
\r
215 NumberFormat nf = NumberFormat.getInstance();
\r
216 nf.setMaximumFractionDigits(4);
\r
217 String out = nf.format(x);
\r
218 logln("0.00159999 formats with 4 fractional digits to " + out);
\r
219 String expected = "0.0016";
\r
220 if (!out.equals(expected))
\r
221 errln("FAIL: Expected " + expected);
\r
225 * A space as a group separator for localized pattern causes
\r
226 * wrong format. WorkAround : use non-breaking space.
\r
228 public void Test4086575() {
\r
230 NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
\r
231 logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern());
\r
232 logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern());
\r
234 // No group separator
\r
235 logln("...applyLocalizedPattern ###,00;(###,00) ");
\r
236 ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)");
\r
237 logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
\r
238 logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
\r
240 logln("nf: " + nf.format(1234)); // 1234,00
\r
241 logln("nf: " + nf.format(-1234)); // (1234,00)
\r
243 // Space as group separator
\r
245 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
\r
246 ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
\r
247 logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
\r
248 logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
\r
249 String buffer = nf.format(1234);
\r
250 if (!buffer.equals("1\u00a0234,00"))
\r
251 errln("nf : " + buffer); // Expect 1 234,00
\r
252 buffer = nf.format(-1234);
\r
253 if (!buffer.equals("(1\u00a0234,00)"))
\r
254 errln("nf : " + buffer); // Expect (1 234,00)
\r
256 // Erroneously prints:
\r
262 * DecimalFormat.parse returns wrong value
\r
264 public void Test4068693()
\r
266 logln("----- Test Application -----");
\r
267 //ParsePosition pos;
\r
268 DecimalFormat df = new DecimalFormat();
\r
269 Number d = df.parse("123.55456", new ParsePosition(0));
\r
270 if (!d.toString().equals("123.55456")) {
\r
271 errln("Result -> " + d.doubleValue());
\r
275 /* bugs 4069754, 4067878
\r
276 * null pointer thrown when accessing a deserialized DecimalFormat
\r
279 public void Test4069754() throws Exception
\r
282 ByteArrayOutputStream baos = new ByteArrayOutputStream();
\r
283 ObjectOutputStream oos = new ObjectOutputStream(baos);
\r
284 myformat it = new myformat();
\r
286 oos.writeObject(it);
\r
290 byte [] bytes = baos.toByteArray();
\r
291 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
\r
292 myformat o = (myformat)ois.readObject();
\r
296 if (!o._dateFormat.equals(it._dateFormat)) {
\r
297 throw new Exception("The saved and loaded object are not equals!");
\r
299 logln("Compare OK!");
\r
300 //} catch (Exception foo) {
\r
301 //errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
\r
306 * DecimalFormat.applyPattern(String) allows illegal patterns
\r
308 public void Test4087251 (){
\r
309 DecimalFormat df = new DecimalFormat();
\r
311 df.applyPattern("#.#.#");
\r
312 logln("toPattern() returns \"" + df.toPattern() + "\"");
\r
313 errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
\r
314 } catch (IllegalArgumentException e) {
\r
315 logln("Caught Illegal Argument Error !");
\r
317 // Second test; added 5/11/98 when reported to fail on 1.2b3
\r
319 df.applyPattern("#0.0#0#0");
\r
320 logln("toPattern() returns \"" + df.toPattern() + "\"");
\r
321 errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
\r
322 } catch (IllegalArgumentException e) {
\r
323 logln("Ok - IllegalArgumentException for #0.0#0#0");
\r
328 * DecimalFormat.format() loses precision
\r
330 public void Test4090489 (){
\r
331 DecimalFormat df = new DecimalFormat();
\r
332 df.setMinimumFractionDigits(10);
\r
333 df.setGroupingUsed(false);
\r
334 double d = 1.000000000000001E7;
\r
335 java.math.BigDecimal bd = new java.math.BigDecimal(d);
\r
336 StringBuffer sb = new StringBuffer("");
\r
337 FieldPosition fp = new FieldPosition(0);
\r
339 logln("BigDecimal.toString(): " + bd.toString());
\r
340 df.format(d, sb, fp);
\r
341 if (!sb.toString().equals("10000000.0000000100")) {
\r
342 errln("DecimalFormat.format(): " + sb.toString());
\r
347 * DecimalFormat.format() loses precision
\r
349 public void Test4090504 ()
\r
353 DecimalFormat df = new DecimalFormat();
\r
357 for (int i = 17; i <= 20; i++) {
\r
358 df.setMaximumFractionDigits(i);
\r
359 sb = new StringBuffer("");
\r
360 fp = new FieldPosition(0);
\r
361 logln(" getMaximumFractionDigits() = " + i);
\r
362 logln(" formated: " + df.format(d, sb, fp));
\r
364 } catch (Exception foo) {
\r
365 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
\r
369 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
\r
371 public void Test4095713 ()
\r
373 DecimalFormat df = new DecimalFormat();
\r
374 String str = "0.1234";
\r
375 Double d1 = new Double(str);
\r
376 Number d2 = df.parse(str, new ParsePosition(0));
\r
377 logln(d1.toString());
\r
378 if (d2.doubleValue() != d1.doubleValue())
\r
379 errln("Bug 4095713 test failed, new double value : " + d2.doubleValue());
\r
383 * DecimalFormat.parse() fails when multiplier is not set to 1
\r
385 public void Test4092561 ()
\r
387 Locale savedLocale = Locale.getDefault();
\r
388 Locale.setDefault(Locale.US);
\r
389 DecimalFormat df = new DecimalFormat();
\r
390 String str = Long.toString(Long.MIN_VALUE);
\r
391 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
\r
392 df.setMultiplier(100);
\r
393 Number num = df.parse(str, new ParsePosition(0));
\r
394 if (num.doubleValue() != -9.223372036854776E16) {
\r
395 errln("Bug 4092561 test failed when multiplier is set to not 1.");
\r
397 Locale.setDefault(savedLocale);
\r
401 * DecimalFormat: Negative format ignored.
\r
403 public void Test4092480 ()
\r
405 DecimalFormat dfFoo = new DecimalFormat("000");
\r
408 dfFoo.applyPattern("0000;-000");
\r
409 if (!dfFoo.toPattern().equals("#0000"))
\r
410 errln("dfFoo.toPattern : " + dfFoo.toPattern());
\r
411 logln(dfFoo.format(42));
\r
412 logln(dfFoo.format(-42));
\r
413 dfFoo.applyPattern("000;-000");
\r
414 if (!dfFoo.toPattern().equals("#000"))
\r
415 errln("dfFoo.toPattern : " + dfFoo.toPattern());
\r
416 logln(dfFoo.format(42));
\r
417 logln(dfFoo.format(-42));
\r
419 dfFoo.applyPattern("000;-0000");
\r
420 if (!dfFoo.toPattern().equals("#000"))
\r
421 errln("dfFoo.toPattern : " + dfFoo.toPattern());
\r
422 logln(dfFoo.format(42));
\r
423 logln(dfFoo.format(-42));
\r
425 dfFoo.applyPattern("0000;-000");
\r
426 if (!dfFoo.toPattern().equals("#0000"))
\r
427 errln("dfFoo.toPattern : " + dfFoo.toPattern());
\r
428 logln(dfFoo.format(42));
\r
429 logln(dfFoo.format(-42));
\r
430 } catch (Exception foo) {
\r
431 errln("Message " + foo.getMessage());
\r
435 * NumberFormat.getCurrencyInstance() produces format that uses
\r
436 * decimal separator instead of monetary decimal separator.
\r
438 * Rewrote this test not to depend on the actual pattern. Pattern should
\r
439 * never contain the monetary separator! Decimal separator in pattern is
\r
440 * interpreted as monetary separator if currency symbol is seen!
\r
442 public void Test4087244 () {
\r
443 Locale de = new Locale("pt", "PT");
\r
444 DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de);
\r
445 DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
\r
446 sym.setMonetaryDecimalSeparator('$');
\r
447 df.setDecimalFormatSymbols(sym);
\r
448 char decSep = sym.getDecimalSeparator();
\r
449 char monSep = sym.getMonetaryDecimalSeparator();
\r
450 //char zero = sym.getZeroDigit(); //The variable is never used
\r
451 if (decSep == monSep) {
\r
452 errln("ERROR in test: want decimal sep != monetary sep");
\r
454 df.setMinimumIntegerDigits(1);
\r
455 df.setMinimumFractionDigits(2);
\r
456 String str = df.format(1.23);
\r
457 String monStr = "1" + monSep + "23";
\r
458 String decStr = "1" + decSep + "23";
\r
459 if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) {
\r
460 logln("OK: 1.23 -> \"" + str + "\" contains \"" +
\r
461 monStr + "\" and not \"" + decStr + '"');
\r
463 errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" +
\r
465 "\" and not \"" + decStr + '"');
\r
470 * Number format data rounding errors for locale FR
\r
472 public void Test4070798 () {
\r
473 NumberFormat formatter;
\r
476 String expectedDefault = "-5\u00a0789,987";
\r
477 String expectedCurrency = "5\u00a0789,98\u00a0F";
\r
478 String expectedPercent = "-578\u00a0998%";
\r
480 String expectedDefault = "-5\u00a0789,988";
\r
481 String expectedCurrency = "5\u00a0789,99\u00a0" + EURO; // euro
\r
482 String expectedPercent = "-578\u00a0999\u00a0%";
\r
484 formatter = NumberFormat.getNumberInstance(Locale.FRANCE);
\r
485 tempString = formatter.format (-5789.9876);
\r
487 if (tempString.equals(expectedDefault)) {
\r
488 logln ("Bug 4070798 default test passed.");
\r
491 " Expected " + expectedDefault +
\r
492 " Received " + tempString );
\r
496 formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE);
\r
497 tempString = formatter.format( 5789.9876 );
\r
499 if (tempString.equals(expectedCurrency) ) {
\r
500 logln ("Bug 4070798 currency test assed.");
\r
503 " Expected " + expectedCurrency +
\r
504 " Received " + tempString );
\r
508 formatter = NumberFormat.getPercentInstance(Locale.FRANCE);
\r
509 tempString = formatter.format (-5789.9876);
\r
511 if (tempString.equals(expectedPercent) ) {
\r
512 logln ("Bug 4070798 percentage test passed.");
\r
515 " Expected " + expectedPercent +
\r
516 " Received " + tempString );
\r
520 * Data rounding errors for French (Canada) locale
\r
522 public void Test4071005 () {
\r
524 NumberFormat formatter;
\r
527 String expectedDefault = "-5 789,987";
\r
528 String expectedCurrency = "5 789,98\u00a0$";
\r
529 String expectedPercent = "-578 998%";
\r
531 String expectedDefault = "-5\u00a0789,988";
\r
532 String expectedCurrency = "5\u00a0789,99\u00a0$";
\r
533 String expectedPercent = "-578\u00a0999\u00A0%";
\r
535 formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
\r
536 tempString = formatter.format (-5789.9876);
\r
537 if (tempString.equals(expectedDefault)) {
\r
538 logln ("Bug 4071005 default test passed.");
\r
541 " Expected " + expectedDefault +
\r
542 " Received " + tempString );
\r
545 formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);
\r
546 tempString = formatter.format( 5789.9876 ) ;
\r
548 if (tempString.equals(expectedCurrency) ) {
\r
549 logln ("Bug 4071005 currency test passed.");
\r
552 " Expected " + expectedCurrency +
\r
553 " Received " + tempString );
\r
555 formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH);
\r
556 tempString = formatter.format (-5789.9876);
\r
558 if (tempString.equals(expectedPercent) ) {
\r
559 logln ("Bug 4071005 percentage test passed.");
\r
562 " Expected " + expectedPercent +
\r
563 " Received " + tempString );
\r
568 * Data rounding errors for German (Germany) locale
\r
570 public void Test4071014 () {
\r
571 NumberFormat formatter;
\r
574 String expectedDefault = "-5.789,987";
\r
575 String expectedCurrency = "5.789,98\u00a0DM";
\r
576 String expectedPercent = "-578.998%";
\r
578 String expectedDefault = "-5.789,988";
\r
579 String expectedCurrency = "5.789,99\u00a0" + EURO;
\r
580 String expectedPercent = "-578.999\u00a0%";
\r
582 formatter = NumberFormat.getNumberInstance(Locale.GERMANY);
\r
583 tempString = formatter.format (-5789.9876);
\r
585 if (tempString.equals(expectedDefault)) {
\r
586 logln ("Bug 4071014 default test passed.");
\r
589 " Expected " + expectedDefault +
\r
590 " Received " + tempString );
\r
593 formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY);
\r
594 tempString = formatter.format( 5789.9876 ) ;
\r
596 if (tempString.equals(expectedCurrency) ) {
\r
597 logln ("Bug 4071014 currency test passed.");
\r
600 " Expected " + expectedCurrency +
\r
601 " Received " + tempString );
\r
604 formatter = NumberFormat.getPercentInstance(Locale.GERMANY);
\r
605 tempString = formatter.format (-5789.9876);
\r
607 if (tempString.equals(expectedPercent) ) {
\r
608 logln ("Bug 4071014 percentage test passed.");
\r
611 " Expected " + expectedPercent +
\r
612 " Received " + tempString );
\r
617 * Data rounding errors for Italian locale number formats
\r
618 * Note- with the Euro, there is no need for currency rounding anymore
\r
620 public void Test4071859 () {
\r
621 NumberFormat formatter;
\r
624 String expectedDefault = "-5.789,987";
\r
625 String expectedCurrency = "-L.\u00a05.789,98";
\r
626 String expectedPercent = "-578.998%";
\r
628 String expectedDefault = "-5.789,988";
\r
629 String expectedCurrency = "-" + EURO + "\u00a05.789,99";
\r
630 String expectedPercent = "-578.999%";
\r
632 formatter = NumberFormat.getNumberInstance(Locale.ITALY);
\r
633 tempString = formatter.format (-5789.9876);
\r
635 if (tempString.equals(expectedDefault)) {
\r
636 logln ("Bug 4071859 default test passed.");
\r
638 errln("a) Failed:" +
\r
639 " Expected " + expectedDefault +
\r
640 " Received " + tempString );
\r
643 formatter = NumberFormat.getCurrencyInstance(Locale.ITALY);
\r
644 tempString = formatter.format( -5789.9876 ) ;
\r
646 if (tempString.equals(expectedCurrency) ) {
\r
647 logln ("Bug 4071859 currency test passed.");
\r
649 errln("b) Failed:" +
\r
650 " Expected " + expectedCurrency +
\r
651 " Received " + tempString );
\r
654 formatter = NumberFormat.getPercentInstance(Locale.ITALY);
\r
655 tempString = formatter.format (-5789.9876);
\r
657 if (tempString.equals(expectedPercent) ) {
\r
658 logln ("Bug 4071859 percentage test passed.");
\r
660 errln("c) Failed:" +
\r
661 " Expected " + expectedPercent +
\r
662 " Received " + tempString );
\r
667 * Test rounding for nearest even.
\r
669 public void Test4093610()
\r
671 DecimalFormat df = new DecimalFormat("#0.#");
\r
672 roundingTest(df, 12.35, "12.4");
\r
673 roundingTest(df, 12.45, "12.4");
\r
674 roundingTest(df, 12.452,"12.5");
\r
675 roundingTest(df, 12.55, "12.6");
\r
676 roundingTest(df, 12.65, "12.6");
\r
677 roundingTest(df, 12.652,"12.7");
\r
678 roundingTest(df, 12.75, "12.8");
\r
679 roundingTest(df, 12.752,"12.8");
\r
680 roundingTest(df, 12.85, "12.8");
\r
681 roundingTest(df, 12.852,"12.9");
\r
682 roundingTest(df, 12.95, "13");
\r
683 roundingTest(df, 12.952,"13");
\r
686 void roundingTest(DecimalFormat df, double x, String expected)
\r
688 String out = df.format(x);
\r
689 logln("" + x + " formats with 1 fractional digits to " + out);
\r
690 if (!out.equals(expected)) errln("FAIL: Expected " + expected);
\r
693 * Tests the setMaximumFractionDigits limit.
\r
695 public void Test4098741()
\r
698 NumberFormat fmt = NumberFormat.getPercentInstance();
\r
699 fmt.setMaximumFractionDigits(20);
\r
700 logln(fmt.format(.001));
\r
701 } catch (Exception foo) {
\r
702 warnln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
\r
706 * Tests illegal pattern exception.
\r
707 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
\r
708 * Part2 has been fixed.
\r
710 public void Test4074454()
\r
713 DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#");
\r
714 logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used"
\r
715 logln("Inconsistent negative pattern is fine.");
\r
716 DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces");
\r
717 String tempString = newFmt.format(3456.78);
\r
718 if (!tempString.equals("3,456.78 p'ieces"))
\r
719 errln("Failed! 3456.78 p'ieces expected, but got : " + tempString);
\r
720 } catch (Exception foo) {
\r
721 warnln("An exception was thrown for any inconsistent negative pattern.");
\r
725 * Tests all different comments.
\r
726 * Response to some comments :
\r
727 * [1] DecimalFormat.parse API documentation is more than just one line.
\r
728 * This is not a reproducable doc error in 116 source code.
\r
729 * [2] See updated javadoc.
\r
731 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
\r
732 * a null object will be returned. The unchanged parse position also
\r
733 * reflects an error.
\r
734 * NumberFormat.parse(String) : If parsing fails, an ParseException
\r
736 * See updated javadoc for more details.
\r
737 * [5] See updated javadoc.
\r
738 * [6] See updated javadoc.
\r
739 * [7] This is a correct behavior if the DateFormat object is linient.
\r
740 * Otherwise, an IllegalArgumentException will be thrown when formatting
\r
741 * "January 35". See GregorianCalendar class javadoc for more details.
\r
743 public void Test4099404()
\r
746 DecimalFormat fmt = new DecimalFormat("000.0#0");
\r
747 logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used"
\r
748 errln("Bug 4099404 failed applying illegal pattern \"000.0#0\"");
\r
749 } catch (Exception foo) {
\r
750 logln("Bug 4099404 pattern \"000.0#0\" passed");
\r
753 DecimalFormat fmt = new DecimalFormat("0#0.000");
\r
754 logln("format 3456.78: " + fmt.format(3456.78)); //fix "The variable 'fmt' is never used"
\r
755 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
\r
756 } catch (Exception foo) {
\r
757 logln("Bug 4099404 pattern \"0#0.000\" passed");
\r
761 * DecimalFormat.applyPattern doesn't set minimum integer digits
\r
763 public void Test4101481()
\r
765 DecimalFormat sdf = new DecimalFormat("#,##0");
\r
766 if (sdf.getMinimumIntegerDigits() != 1)
\r
767 errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits());
\r
770 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
\r
772 public void Test4052223()
\r
775 DecimalFormat fmt = new DecimalFormat("#,#00.00");
\r
776 Number num = fmt.parse("abc3");
\r
777 errln("Bug 4052223 failed : can't parse string \"a\". Got " + num);
\r
778 } catch (ParseException foo) {
\r
779 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
\r
783 * API tests for API addition request A9.
\r
785 public void Test4061302()
\r
787 DecimalFormatSymbols fmt = new DecimalFormatSymbols();
\r
788 String currency = fmt.getCurrencySymbol();
\r
789 String intlCurrency = fmt.getInternationalCurrencySymbol();
\r
790 char monDecSeparator = fmt.getMonetaryDecimalSeparator();
\r
791 if (currency.equals("") ||
\r
792 intlCurrency.equals("") ||
\r
793 monDecSeparator == 0) {
\r
794 errln("getCurrencySymbols failed, got empty string.");
\r
796 logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
\r
797 fmt.setCurrencySymbol("XYZ");
\r
798 fmt.setInternationalCurrencySymbol("ABC");
\r
799 fmt.setMonetaryDecimalSeparator('*');
\r
800 currency = fmt.getCurrencySymbol();
\r
801 intlCurrency = fmt.getInternationalCurrencySymbol();
\r
802 monDecSeparator = fmt.getMonetaryDecimalSeparator();
\r
803 if (!currency.equals("XYZ") ||
\r
804 !intlCurrency.equals("ABC") ||
\r
805 monDecSeparator != '*') {
\r
806 errln("setCurrencySymbols failed.");
\r
808 logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
\r
811 * API tests for API addition request A23. FieldPosition.getBeginIndex and
\r
812 * FieldPosition.getEndIndex.
\r
814 public void Test4062486()
\r
816 DecimalFormat fmt = new DecimalFormat("#,##0.00");
\r
817 StringBuffer formatted = new StringBuffer();
\r
818 FieldPosition field = new FieldPosition(0);
\r
819 Double num = new Double(1234.5);
\r
820 fmt.format(num, formatted, field);
\r
821 if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
\r
822 errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
\r
823 field.setBeginIndex(7);
\r
824 field.setEndIndex(4);
\r
825 if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
\r
826 errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
\r
830 * DecimalFormat.parse incorrectly works with a group separator.
\r
832 public void Test4108738()
\r
835 DecimalFormat df = new DecimalFormat("#,##0.###", new
\r
836 DecimalFormatSymbols(java.util.Locale.US));
\r
837 String text = "1.222,111";
\r
838 Number num = df.parse(text,new ParsePosition(0));
\r
839 if (!num.toString().equals("1.222"))
\r
840 errln("\"" + text + "\" is parsed as " + num);
\r
841 text = "1.222x111";
\r
842 num = df.parse(text,new ParsePosition(0));
\r
843 if (!num.toString().equals("1.222"))
\r
844 errln("\"" + text + "\" is parsed as " + num);
\r
848 * DecimalFormat.format() incorrectly formats negative doubles.
\r
850 public void Test4106658()
\r
852 Locale savedLocale = Locale.getDefault();
\r
853 Locale.setDefault(Locale.US);
\r
854 DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706
\r
856 double d2 = -0.0001;
\r
857 StringBuffer buffer = new StringBuffer();
\r
858 logln("pattern: \"" + df.toPattern() + "\"");
\r
859 df.format(d1, buffer, new FieldPosition(0));
\r
860 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
\r
861 errln(d1 + " is formatted as " + buffer);
\r
863 buffer.setLength(0);
\r
864 df.format(d2, buffer, new FieldPosition(0));
\r
865 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
\r
866 errln(d2 + " is formatted as " + buffer);
\r
868 Locale.setDefault(savedLocale);
\r
872 * DecimalFormat.parse returns 0 if string parameter is incorrect.
\r
874 public void Test4106662()
\r
876 DecimalFormat df = new DecimalFormat();
\r
878 ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0);
\r
880 logln("pattern: \"" + df.toPattern() + "\"");
\r
881 Number num = df.parse(text, pos1);
\r
883 errln("Test Failed: \"" + text + "\" is parsed as " + num);
\r
886 df = new DecimalFormat("$###.00");
\r
887 num = df.parse("$", pos2);
\r
889 errln("Test Failed: \"$\" is parsed as " + num);
\r
894 * NumberFormat.parse doesn't return null
\r
896 public void Test4114639()
\r
898 NumberFormat format = NumberFormat.getInstance();
\r
899 String text = "time 10:x";
\r
900 ParsePosition pos = new ParsePosition(8);
\r
901 Number result = format.parse(text, pos);
\r
902 if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't
\r
906 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
\r
908 public void Test4106664()
\r
910 DecimalFormat df = new DecimalFormat();
\r
911 long n = 1234567890123456L;
\r
913 BigInteger bigN = BigInteger.valueOf(n);
\r
914 bigN = bigN.multiply(BigInteger.valueOf(m));
\r
915 df.setMultiplier(m);
\r
916 df.setGroupingUsed(false);
\r
917 logln("formated: " +
\r
918 df.format(n, new StringBuffer(), new FieldPosition(0)));
\r
919 logln("expected: " + bigN.toString());
\r
922 * DecimalFormat.format incorrectly formats -0.0.
\r
924 public void Test4106667()
\r
926 Locale savedLocale = Locale.getDefault();
\r
927 Locale.setDefault(Locale.US);
\r
928 DecimalFormat df = new DecimalFormat();
\r
929 df.setPositivePrefix("+");
\r
931 logln("pattern: \"" + df.toPattern() + "\"");
\r
932 StringBuffer buffer = new StringBuffer();
\r
933 df.format(d, buffer, new FieldPosition(0));
\r
934 if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
\r
935 errln(d + " is formatted as " + buffer);
\r
937 Locale.setDefault(savedLocale);
\r
941 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
\r
943 public void Test4110936()
\r
945 NumberFormat nf = NumberFormat.getInstance();
\r
946 nf.setMaximumIntegerDigits(128);
\r
947 logln("setMaximumIntegerDigits(128)");
\r
948 if (nf.getMaximumIntegerDigits() != 128)
\r
949 errln("getMaximumIntegerDigits() returns " +
\r
950 nf.getMaximumIntegerDigits());
\r
954 * Locale data should use generic currency symbol
\r
956 * 1) Make sure that all currency formats use the generic currency symbol.
\r
957 * 2) Make sure we get the same results using the generic symbol or a
\r
960 public void Test4122840()
\r
962 Locale[] locales = NumberFormat.getAvailableLocales();
\r
964 for (int i = 0; i < locales.length; i++) {
\r
965 UResourceBundle rb = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,locales[i]);
\r
968 // Get the currency pattern for this locale. We have to fish it
\r
969 // out of the ResourceBundle directly, since DecimalFormat.toPattern
\r
970 // will return the localized symbol, not \00a4
\r
972 UResourceBundle numPatterns = rb.get("NumberPatterns");
\r
973 String pattern = numPatterns.getString(1);
\r
975 if (pattern.indexOf('\u00A4') == -1 ) { // 'x' not "x" -- workaround bug in IBM JDK 1.4.1
\r
976 errln("Currency format for " + locales[i] +
\r
977 " does not contain generic currency symbol:" +
\r
981 // Create a DecimalFormat using the pattern we got and format a number
\r
982 DecimalFormatSymbols symbols = new DecimalFormatSymbols(locales[i]);
\r
983 DecimalFormat fmt1 = new DecimalFormat(pattern, symbols);
\r
985 String result1 = fmt1.format(1.111);
\r
988 // Now substitute in the locale's currency symbol and create another
\r
989 // pattern. Replace the decimal separator with the monetary separator.
\r
991 //char decSep = symbols.getDecimalSeparator(); //The variable is never used
\r
992 char monSep = symbols.getMonetaryDecimalSeparator();
\r
993 StringBuffer buf = new StringBuffer(pattern);
\r
994 for (int j = 0; j < buf.length(); j++) {
\r
995 if (buf.charAt(j) == '\u00a4') {
\r
996 String cur = "'" + symbols.getCurrencySymbol() + "'";
\r
997 buf.replace(j, j+1, cur);
\r
998 j += cur.length() - 1;
\r
1001 symbols.setDecimalSeparator(monSep);
\r
1002 DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols);
\r
1004 String result2 = fmt2.format(1.111);
\r
1006 // NOTE: en_IN is a special case (ChoiceFormat currency display name)
\r
1007 if (!result1.equals(result2) &&
\r
1008 !locales[i].toString().equals("en_IN")) {
\r
1009 errln("Results for " + locales[i] + " differ: " +
\r
1010 result1 + " vs " + result2);
\r
1016 * DecimalFormat.format() delivers wrong string.
\r
1018 public void Test4125885()
\r
1020 double rate = 12.34;
\r
1021 DecimalFormat formatDec = new DecimalFormat ("000.00");
\r
1022 logln("toPattern: " + formatDec.toPattern());
\r
1023 String rateString= formatDec.format(rate);
\r
1024 if (!rateString.equals("012.34"))
\r
1025 errln("result : " + rateString + " expected : 012.34");
\r
1028 formatDec = new DecimalFormat ("+000.00%;-000.00%");
\r
1029 logln("toPattern: " + formatDec.toPattern());
\r
1030 rateString= formatDec.format(rate);
\r
1031 if (!rateString.equals("+012.34%"))
\r
1032 errln("result : " + rateString + " expected : +012.34%");
\r
1037 * DecimalFormat produces extra zeros when formatting numbers.
\r
1039 public void Test4134034() {
\r
1040 DecimalFormat nf = new DecimalFormat("##,###,###.00");
\r
1042 String f = nf.format(9.02);
\r
1043 if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02");
\r
1046 if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00");
\r
1050 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
\r
1051 * a duplicate of 4134034.
\r
1053 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
\r
1054 * Possibly related to bug 4125885.
\r
1056 * This class demonstrates a regression in version 1.1.6
\r
1057 * of DecimalFormat class.
\r
1060 * Value 1.2 Format #.00 Result '01.20' !!!wrong
\r
1061 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
\r
1062 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
\r
1063 * Value 1.2 Format #0.0# Result '1.2'
\r
1064 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
\r
1067 * Value 1.2 Format #.00 Result '1.20'
\r
1068 * Value 1.2 Format 0.00 Result '1.20'
\r
1069 * Value 1.2 Format 00.00 Result '01.20'
\r
1070 * Value 1.2 Format #0.0# Result '1.2'
\r
1071 * Value 1.2 Format #0.00 Result '1.20'
\r
1073 public void Test4134300() {
\r
1075 // Pattern Expected string
\r
1082 for (int i=0; i<DATA.length; i+=2) {
\r
1083 String result = new DecimalFormat(DATA[i]).format(1.2);
\r
1084 if (!result.equals(DATA[i+1])) {
\r
1085 errln("Fail: 1.2 x " + DATA[i] + " = " + result +
\r
1086 "; want " + DATA[i+1]);
\r
1089 logln("Ok: 1.2 x " + DATA[i] + " = " + result);
\r
1095 * Empty pattern produces double negative prefix.
\r
1097 public void Test4140009() {
\r
1098 final double IN[] = { 123.456, -123.456 };
\r
1099 final String OUT[] = { "123.456", "-123.456" };
\r
1100 for (int i=0; i<2; ++i) {
\r
1101 DecimalFormat f = null;
\r
1104 f = new DecimalFormat("",
\r
1105 new DecimalFormatSymbols(Locale.ENGLISH));
\r
1108 f = new DecimalFormat("#.#",
\r
1109 new DecimalFormatSymbols(Locale.ENGLISH));
\r
1110 f.applyPattern("");
\r
1113 for (int j=0; j<2; ++j) {
\r
1114 assertEquals("<empty pat " + i + ">.format(" + IN[j] + ")",
\r
1115 OUT[j], f.format(IN[j]));
\r
1121 * BigDecimal numbers get their fractions truncated by NumberFormat.
\r
1123 public void Test4141750() {
\r
1125 String str = "12345.67";
\r
1126 java.math.BigDecimal bd = new java.math.BigDecimal(str);
\r
1127 String sd = NumberFormat.getInstance(Locale.US).format(bd);
\r
1128 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
\r
1130 catch (Exception e) {
\r
1131 warnln(e.toString());
\r
1132 //e.printStackTrace();
\r
1137 * DecimalFormat toPattern() doesn't quote special characters or handle
\r
1140 public void Test4145457() {
\r
1142 DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
\r
1143 DecimalFormatSymbols sym = nf.getDecimalFormatSymbols();
\r
1144 sym.setDecimalSeparator('\'');
\r
1145 nf.setDecimalFormatSymbols(sym);
\r
1146 double pi = 3.14159;
\r
1148 String[] PATS = { "#.00 'num''ber'", "''#.00''" };
\r
1150 for (int i=0; i<PATS.length; ++i) {
\r
1151 nf.applyPattern(PATS[i]);
\r
1152 String out = nf.format(pi);
\r
1153 String pat = nf.toPattern();
\r
1154 double val = nf.parse(out).doubleValue();
\r
1156 nf.applyPattern(pat);
\r
1157 String out2 = nf.format(pi);
\r
1158 String pat2 = nf.toPattern();
\r
1159 double val2 = nf.parse(out2).doubleValue();
\r
1161 if (!pat.equals(pat2))
\r
1162 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
\r
1163 pat + "\" vs. \"" + pat2 + "\"");
\r
1165 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
\r
1167 if (val == val2 && out.equals(out2)) {
\r
1168 logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" +
\r
1169 out + "\" -> " + val + " -> \"" +
\r
1170 out2 + "\" -> " + val2);
\r
1173 errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" +
\r
1174 out + "\" -> " + val + " -> \"" +
\r
1175 out2 + "\" -> " + val2);
\r
1179 catch (ParseException e) {
\r
1180 errln("Fail: " + e);
\r
1181 e.printStackTrace();
\r
1186 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
\r
1187 * CANNOT REPRODUCE
\r
1188 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
\r
1190 public void Test4147295() {
\r
1191 DecimalFormat sdf = new DecimalFormat();
\r
1192 String pattern = "#,###";
\r
1193 logln("Applying pattern \"" + pattern + "\"");
\r
1194 sdf.applyPattern(pattern);
\r
1195 int minIntDig = sdf.getMinimumIntegerDigits();
\r
1196 if (minIntDig != 0) {
\r
1197 errln("Test failed");
\r
1198 errln(" Minimum integer digits : " + minIntDig);
\r
1199 errln(" new pattern: " + sdf.toPattern());
\r
1201 logln("Test passed");
\r
1202 logln(" Minimum integer digits : " + minIntDig);
\r
1207 * DecimalFormat formats -0.0 as +0.0
\r
1208 * See also older related bug 4106658, 4106667
\r
1210 public void Test4147706() {
\r
1211 DecimalFormat df = new DecimalFormat("#,##0.0##");
\r
1212 df.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.ENGLISH));
\r
1214 double d2 = -0.0001;
\r
1215 StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0));
\r
1216 StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0));
\r
1217 if (!f1.toString().equals("-0.0")) {
\r
1218 errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"');
\r
1220 if (!f2.toString().equals("-0.0")) {
\r
1221 errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"');
\r
1226 * NumberFormat cannot format Double.MAX_VALUE
\r
1228 public void Test4162198() {
\r
1229 double dbl = Double.MAX_VALUE;
\r
1230 NumberFormat f = NumberFormat.getInstance();
\r
1231 f.setMaximumFractionDigits(Integer.MAX_VALUE);
\r
1232 f.setMaximumIntegerDigits(Integer.MAX_VALUE);
\r
1233 String s = f.format(dbl);
\r
1234 logln("The number " + dbl + " formatted to " + s);
\r
1238 } catch (java.text.ParseException e) {
\r
1239 errln("Caught a ParseException:");
\r
1240 e.printStackTrace();
\r
1242 logln("The string " + s + " parsed as " + n);
\r
1243 if (n.doubleValue() != dbl) {
\r
1244 errln("Round trip failure");
\r
1249 * NumberFormat does not parse negative zero.
\r
1251 public void Test4162852() throws ParseException {
\r
1252 for (int i=0; i<2; ++i) {
\r
1253 NumberFormat f = (i == 0) ? NumberFormat.getInstance()
\r
1254 : NumberFormat.getPercentInstance();
\r
1256 String s = f.format(d);
\r
1257 double e = f.parse(s).doubleValue();
\r
1260 '"' + s + '"' + " -> " +
\r
1262 if (e != 0.0 || 1.0/e > 0.0) {
\r
1263 logln("Failed to parse negative zero");
\r
1269 * NumberFormat truncates data
\r
1271 public void Test4167494() throws Exception {
\r
1272 NumberFormat fmt = NumberFormat.getInstance(Locale.US);
\r
1274 double a = Double.MAX_VALUE;
\r
1275 String s = fmt.format(a);
\r
1276 double b = fmt.parse(s).doubleValue();
\r
1277 boolean match = a == b;
\r
1279 logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
\r
1281 errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
\r
1284 // We don't test Double.MIN_VALUE because the locale data for the US
\r
1285 // currently doesn't specify enough digits to display Double.MIN_VALUE.
\r
1286 // This is correct for now; however, we leave this here as a reminder
\r
1287 // in case we want to address this later.
\r
1289 a = Double.MIN_VALUE;
\r
1290 s = fmt.format(a);
\r
1291 b = fmt.parse(s).doubleValue();
\r
1294 logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
\r
1296 errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
\r
1302 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
\r
1304 public void Test4170798() {
\r
1305 Locale savedLocale = Locale.getDefault();
\r
1306 Locale.setDefault(Locale.US);
\r
1307 DecimalFormat df = new DecimalFormat();
\r
1308 df.setParseIntegerOnly(true);
\r
1309 Number n = df.parse("-0.0", new ParsePosition(0));
\r
1310 if (!(n instanceof Double)
\r
1311 || n.intValue() != 0) {
\r
1312 errln("FAIL: parse(\"-0.0\") returns " +
\r
1313 n + " (" + n.getClass().getName() + ')');
\r
1315 Locale.setDefault(savedLocale);
\r
1319 * toPattern only puts the first grouping separator in.
\r
1321 public void Test4176114() {
\r
1324 "000", "#000", // No grouping
\r
1325 "#000", "#000", // No grouping
\r
1328 "0,000", "#0,000",
\r
1329 "00,000", "#00,000",
\r
1330 "000,000", "#,000,000",
\r
1331 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
\r
1333 for (int i=0; i<DATA.length; i+=2) {
\r
1334 DecimalFormat df = new DecimalFormat(DATA[i]);
\r
1335 String s = df.toPattern();
\r
1336 if (!s.equals(DATA[i+1])) {
\r
1337 errln("FAIL: " + DATA[i] + " -> " + s + ", want " + DATA[i+1]);
\r
1343 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
\r
1345 public void Test4179818() {
\r
1347 // Input Pattern Expected output
\r
1348 "1.2511", "#.#", "1.3",
\r
1349 "1.2501", "#.#", "1.3",
\r
1350 "0.9999", "#", "1",
\r
1352 DecimalFormat fmt = new DecimalFormat("#",
\r
1353 new DecimalFormatSymbols(Locale.US));
\r
1354 for (int i=0; i<DATA.length; i+=3) {
\r
1355 double in = Double.valueOf(DATA[i]).doubleValue();
\r
1356 String pat = DATA[i+1];
\r
1357 String exp = DATA[i+2];
\r
1358 fmt.applyPattern(pat);
\r
1359 String out = fmt.format(in);
\r
1360 if (out.equals(exp)) {
\r
1361 logln("Ok: " + in + " x " + pat + " = " + out);
\r
1363 errln("FAIL: " + in + " x " + pat + " = " + out +
\r
1364 ", expected " + exp);
\r
1369 public void Test4185761() throws IOException, ClassNotFoundException {
\r
1370 ByteArrayOutputStream baos = new ByteArrayOutputStream();
\r
1371 ObjectOutputStream oos = new ObjectOutputStream(baos);
\r
1373 NumberFormat nf = NumberFormat.getInstance(Locale.US);
\r
1375 // Set special values we are going to search for in the output byte stream
\r
1376 // These are all legal values.
\r
1377 nf.setMinimumIntegerDigits(0x111); // Keep under 309
\r
1378 nf.setMaximumIntegerDigits(0x112); // Keep under 309
\r
1379 nf.setMinimumFractionDigits(0x113); // Keep under 340
\r
1380 nf.setMaximumFractionDigits(0x114); // Keep under 340
\r
1382 oos.writeObject(nf);
\r
1386 byte[] bytes = baos.toByteArray();
\r
1388 // Scan for locations of min/max int/fract values in the byte array.
\r
1389 // At the moment (ICU4J 2.1), there is only one instance of each target pair
\r
1390 // in the byte stream, so assume first match is it. Note this is not entirely
\r
1391 // failsafe, and needs to be checked if we change the package or structure of
\r
1393 // Current positions are 890, 880, 886, 876
\r
1394 int[] offsets = new int[4];
\r
1395 for (int i = 0; i < bytes.length - 1; ++i) {
\r
1396 if (bytes[i] == 0x01) { // high byte
\r
1397 for (int j = 0; j < offsets.length; ++j) {
\r
1398 if ((offsets[j] == 0) && (bytes[i+1] == (0x11 + j))) { // low byte
\r
1407 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
\r
1408 Object o = ois.readObject();
\r
1411 if (!nf.equals(o)) {
\r
1412 errln("Fail: NumberFormat serialization/equality bug");
\r
1414 logln("NumberFormat serialization/equality is OKAY.");
\r
1418 // Change the values in the byte stream so that min > max.
\r
1419 // Numberformat should catch this and throw an exception.
\r
1420 for (int i = 0; i < offsets.length; ++i) {
\r
1421 bytes[offsets[i]] = (byte)(4 - i);
\r
1425 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
\r
1427 NumberFormat format = (NumberFormat) ois.readObject();
\r
1428 logln("format: " + format.format(1234.56)); //fix "The variable is never used"
\r
1429 errln("FAIL: Deserialized bogus NumberFormat with minXDigits > maxXDigits");
\r
1430 } catch (InvalidObjectException e) {
\r
1431 logln("Ok: " + e.getMessage());
\r
1435 // Set values so they are too high, but min <= max
\r
1436 // Format should pass the min <= max test, and DecimalFormat should reset to current maximum
\r
1437 // (for compatibility with versions streamed out before the maximums were imposed).
\r
1438 for (int i = 0; i < offsets.length; ++i) {
\r
1439 bytes[offsets[i]] = 4;
\r
1443 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
\r
1444 NumberFormat format = (NumberFormat) ois.readObject();
\r
1445 //For compatibility with previous version
\r
1446 if ((format.getMaximumIntegerDigits() != 309)
\r
1447 || format.getMaximumFractionDigits() != 340) {
\r
1448 errln("FAIL: Deserialized bogus NumberFormat with values out of range," +
\r
1449 " intMin: " + format.getMinimumIntegerDigits() +
\r
1450 " intMax: " + format.getMaximumIntegerDigits() +
\r
1451 " fracMin: " + format.getMinimumFractionDigits() +
\r
1452 " fracMax: " + format.getMaximumFractionDigits());
\r
1454 logln("Ok: Digit count out of range");
\r
1461 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
\r
1462 * This includes the minus sign, currency symbol, international currency
\r
1463 * symbol, percent, and permille. This is filed as bugs 4212072 and
\r
1466 public void Test4212072() throws IOException, ClassNotFoundException {
\r
1467 DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
\r
1468 DecimalFormat fmt = new DecimalFormat("#", sym);
\r
1470 sym.setMinusSign('^');
\r
1471 fmt.setDecimalFormatSymbols(sym);
\r
1472 if (!fmt.format(-1).equals("^1")) {
\r
1473 errln("FAIL: -1 x (minus=^) -> " + fmt.format(-1) +
\r
1476 if (!fmt.getNegativePrefix().equals("^")) {
\r
1477 errln("FAIL: (minus=^).getNegativePrefix -> " +
\r
1478 fmt.getNegativePrefix() + ", exp ^");
\r
1480 sym.setMinusSign('-');
\r
1482 fmt.applyPattern("#%");
\r
1483 sym.setPercent('^');
\r
1484 fmt.setDecimalFormatSymbols(sym);
\r
1485 if (!fmt.format(0.25).equals("25^")) {
\r
1486 errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) +
\r
1489 if (!fmt.getPositiveSuffix().equals("^")) {
\r
1490 errln("FAIL: (percent=^).getPositiveSuffix -> " +
\r
1491 fmt.getPositiveSuffix() + ", exp ^");
\r
1493 sym.setPercent('%');
\r
1495 fmt.applyPattern("#\u2030");
\r
1496 sym.setPerMill('^');
\r
1497 fmt.setDecimalFormatSymbols(sym);
\r
1498 if (!fmt.format(0.25).equals("250^")) {
\r
1499 errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) +
\r
1502 if (!fmt.getPositiveSuffix().equals("^")) {
\r
1503 errln("FAIL: (permill=^).getPositiveSuffix -> " +
\r
1504 fmt.getPositiveSuffix() + ", exp ^");
\r
1506 sym.setPerMill('\u2030');
\r
1508 fmt.applyPattern("\u00A4#.00");
\r
1509 sym.setCurrencySymbol("usd");
\r
1510 fmt.setDecimalFormatSymbols(sym);
\r
1511 if (!fmt.format(12.5).equals("usd12.50")) {
\r
1512 errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) +
\r
1513 ", exp usd12.50");
\r
1515 if (!fmt.getPositivePrefix().equals("usd")) {
\r
1516 errln("FAIL: (currency=usd).getPositivePrefix -> " +
\r
1517 fmt.getPositivePrefix() + ", exp usd");
\r
1519 sym.setCurrencySymbol("$");
\r
1521 fmt.applyPattern("\u00A4\u00A4#.00");
\r
1522 sym.setInternationalCurrencySymbol("DOL");
\r
1523 fmt.setDecimalFormatSymbols(sym);
\r
1524 if (!fmt.format(12.5).equals("DOL12.50")) {
\r
1525 errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) +
\r
1526 ", exp DOL12.50");
\r
1528 if (!fmt.getPositivePrefix().equals("DOL")) {
\r
1529 errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " +
\r
1530 fmt.getPositivePrefix() + ", exp DOL");
\r
1532 sym.setInternationalCurrencySymbol("USD");
\r
1534 if (VersionInfo.ICU_VERSION == VersionInfo.getInstance(2,2)) {
\r
1535 // bug in 2.2 that fails this test
\r
1536 // to be fixed in the later versions
\r
1537 System.out.println("\n Test skipped for release 2.2");
\r
1541 // Since the pattern logic has changed, make sure that patterns round
\r
1542 // trip properly. Test stream in/out integrity too.
\r
1543 Locale[] avail = NumberFormat.getAvailableLocales();
\r
1544 for (int i=0; i<avail.length; ++i) {
\r
1545 for (int j=0; j<3; ++j) {
\r
1549 nf = NumberFormat.getInstance(avail[i]);
\r
1552 nf = NumberFormat.getCurrencyInstance(avail[i]);
\r
1555 nf = NumberFormat.getPercentInstance(avail[i]);
\r
1558 DecimalFormat df = (DecimalFormat) nf;
\r
1560 // Test toPattern/applyPattern round trip
\r
1561 String pat = df.toPattern();
\r
1562 DecimalFormatSymbols symb = new DecimalFormatSymbols(avail[i]);
\r
1563 DecimalFormat f2 = new DecimalFormat(pat, symb);
\r
1564 if (!df.equals(f2)) {
\r
1565 errln("FAIL: " + avail[i] + " #" + j + " -> \"" + pat +
\r
1566 "\" -> \"" + f2.toPattern() + '"');
\r
1569 // Test toLocalizedPattern/applyLocalizedPattern round trip
\r
1570 pat = df.toLocalizedPattern();
\r
1572 f2.applyLocalizedPattern(pat);
\r
1574 String s1 = f2.format(123456);
\r
1575 String s2 = df.format(123456);
\r
1576 if(!s1.equals(s2)){
\r
1577 errln("FAIL: " + avail[i] + " #" + j + " -> localized \"" + s2 +
\r
1578 "\" -> \"" + s2 + '"'+ " in locale "+df.getLocale(ULocale.ACTUAL_LOCALE));
\r
1581 if (!df.equals(f2)) {
\r
1582 errln("FAIL: " + avail[i] + " #" + j + " -> localized \"" + pat +
\r
1583 "\" -> \"" + f2.toLocalizedPattern() + '"'+ " in locale "+df.getLocale(ULocale.ACTUAL_LOCALE));
\r
1584 errln("s1: "+s1+" s2: "+s2);
\r
1587 }catch(IllegalArgumentException ex){
\r
1588 errln(ex.getMessage()+" for locale "+ df.getLocale(ULocale.ACTUAL_LOCALE));
\r
1592 // Test writeObject/readObject round trip
\r
1593 ByteArrayOutputStream baos = new ByteArrayOutputStream();
\r
1594 ObjectOutputStream oos = new ObjectOutputStream(baos);
\r
1595 oos.writeObject(df);
\r
1598 byte[] bytes = baos.toByteArray();
\r
1599 ObjectInputStream ois =
\r
1600 new ObjectInputStream(new ByteArrayInputStream(bytes));
\r
1601 f2 = (DecimalFormat) ois.readObject();
\r
1602 if (!df.equals(f2)) {
\r
1603 errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat +
\r
1605 (f2 != null ? ("\""+f2.toPattern()+'"') : "null"));
\r
1612 // Make sure that all special characters, when quoted in a suffix or
\r
1613 // prefix, lose their special meaning.
\r
1614 char[] SPECIALS = { '0', ',', '.', '\u2030', '%', '#',
\r
1615 ';', 'E', '*', '+', '-' };
\r
1616 sym = new DecimalFormatSymbols(Locale.US);
\r
1617 for (int j=0; j<SPECIALS.length; ++j) {
\r
1618 char special = SPECIALS[j];
\r
1619 String pat = "'" + special + "'#0'" + special + "'";
\r
1621 fmt = new DecimalFormat(pat, sym);
\r
1622 String pat2 = fmt.toPattern();
\r
1623 if (!pat.equals(pat2)) {
\r
1624 errln("FAIL: Pattern \"" + pat + "\" => toPattern() => \"" +
\r
1627 String s = fmt.format(123);
\r
1628 String exp = "" + special + "123" + special;
\r
1629 if (!s.equals(exp)) {
\r
1630 errln("FAIL: 123 x \"" + pat + "\" => \"" + s + "\", exp \"" +
\r
1633 } catch (IllegalArgumentException e) {
\r
1634 errln("FAIL: Pattern \"" + pat + "\" => " + e.getMessage());
\r
1640 * DecimalFormat.parse() fails for mulipliers 2^n.
\r
1642 public void Test4216742() throws ParseException {
\r
1643 DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US);
\r
1644 long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L};
\r
1645 for (int i=0; i<DATA.length; ++i) {
\r
1646 String str = Long.toString(DATA[i]);
\r
1647 for (int m = 1; m <= 100; m++) {
\r
1648 fmt.setMultiplier(m);
\r
1649 long n = ((Number) fmt.parse(str)).longValue();
\r
1650 if (n > 0 != DATA[i] > 0) {
\r
1651 errln("\"" + str + "\" parse(x " + fmt.getMultiplier() +
\r
1659 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
\r
1662 public void Test4217661() {
\r
1664 new Double(0.001), "0",
\r
1665 new Double(1.001), "1",
\r
1666 new Double(0.006), "0.01",
\r
1667 new Double(1.006), "1.01",
\r
1669 NumberFormat fmt = NumberFormat.getInstance(Locale.US);
\r
1670 fmt.setMaximumFractionDigits(2);
\r
1671 for (int i=0; i<DATA.length; i+=2) {
\r
1672 String s = fmt.format(((Double) DATA[i]).doubleValue());
\r
1673 if (!s.equals(DATA[i+1])) {
\r
1674 errln("FAIL: Got " + s + ", exp " + DATA[i+1]);
\r
1680 * 4243011: Formatting .5 rounds to "1" instead of "0"
\r
1682 public void Test4243011() {
\r
1683 double DATA[] = {0.5, 1.5, 2.5, 3.5, 4.5};
\r
1684 String EXPECTED[] = {"0.", "2.", "2.", "4.", "4."};
\r
1686 DecimalFormat format = new DecimalFormat("0.");
\r
1687 for (int i = 0; i < DATA.length; i++) {
\r
1688 String result = format.format(DATA[i]);
\r
1689 if (result.equals(EXPECTED[i])) {
\r
1690 logln("OK: got " + result);
\r
1692 errln("FAIL: got " + result);
\r
1698 * 4243108: format(0.0) gives "0.1" if preceded by parse("99.99")
\r
1700 public void Test4243108() {
\r
1701 DecimalFormat f = new DecimalFormat("#.#");
\r
1702 String result = f.format(0.0);
\r
1703 if (result.equals("0")) {
\r
1704 logln("OK: got " + result);
\r
1706 errln("FAIL: got " + result);
\r
1709 double dResult = f.parse("99.99").doubleValue();
\r
1710 if (dResult == 99.99) {
\r
1711 logln("OK: got " + dResult);
\r
1713 errln("FAIL: got " + dResult);
\r
1715 } catch (ParseException e) {
\r
1716 errln("Caught a ParseException:");
\r
1717 e.printStackTrace();
\r
1719 result = f.format(0.0);
\r
1720 if (result.equals("0")) {
\r
1721 logln("OK: got " + result);
\r
1723 errln("FAIL: got " + result);
\r
1728 * 4330377: DecimalFormat engineering notation gives incorrect results
\r
1730 public void test4330377() {
\r
1732 double[] input = {5000.0, 500.0, 50.0, 5.0, 0.5, 0.05, 0.005, 0.0005,
\r
1733 5050.0, 505.0, 50.5, 5.05, 0.505, 0.0505, 0.00505, 0.000505};
\r
1734 String[] pattern = {"000.#E0", "##0.#E0", "#00.#E0"};
\r
1735 String[][] expected = {
\r
1736 // it's questionable whether "#00.#E0" should result in post-decimal
\r
1737 // zeroes, i.e., whether "5.0E3", "5.0E0", "5.0E-3" are really good
\r
1738 {"500E1", "5E3", "5.0E3"},
\r
1739 {"500E0", "500E0", "500E0"},
\r
1740 {"500E-1", "50E0", "50E0"},
\r
1741 {"500E-2", "5E0", "5.0E0"},
\r
1742 {"500E-3", "500E-3", "500E-3"},
\r
1743 {"500E-4", "50E-3", "50E-3"},
\r
1744 {"500E-5", "5E-3", "5.0E-3"},
\r
1745 {"500E-6", "500E-6", "500E-6"},
\r
1746 {"505E1", "5.05E3", "5.05E3"},
\r
1747 {"505E0", "505E0", "505E0"},
\r
1748 {"505E-1", "50.5E0", "50.5E0"},
\r
1749 {"505E-2", "5.05E0", "5.05E0"},
\r
1750 {"505E-3", "505E-3", "505E-3"},
\r
1751 {"505E-4", "50.5E-3", "50.5E-3"},
\r
1752 {"505E-5", "5.05E-3", "5.05E-3"},
\r
1753 {"505E-6", "505E-6", "505E-6"}
\r
1755 for (int i = 0; i < input.length; i++) {
\r
1756 for (int j = 0; j < pattern.length; j++) {
\r
1757 DecimalFormat format = new DecimalFormat(pattern[j]);
\r
1758 String result = format.format(input[i]);
\r
1759 if (!result.equals(expected[i][j])) {
\r
1760 errln("FAIL: input: " + input[i] +
\r
1761 ", pattern: " + pattern[j] +
\r
1762 ", expected: " + expected[i][j] +
\r
1763 ", got: " + result);
\r
1771 * 4233840: NumberFormat does not round correctly
\r
1773 public void test4233840() {
\r
1774 float f = 0.0099f;
\r
1776 NumberFormat nf = new DecimalFormat("0.##", new DecimalFormatSymbols(Locale.US));
\r
1777 nf.setMinimumFractionDigits(2);
\r
1779 String result = nf.format(f);
\r
1781 if (!result.equals("0.01")) {
\r
1782 errln("FAIL: input: " + f + ", expected: 0.01, got: " + result);
\r
1787 * 4241880: Decimal format doesnt round a double properly when the number is less than 1
\r
1789 public void test4241880() {
\r
1790 Locale savedLocale = Locale.getDefault();
\r
1791 Locale.setDefault(Locale.US);
\r
1792 double[] input = {
\r
1793 .019, .009, .015, .016, .014,
\r
1794 .004, .005, .006, .007, .008,
\r
1795 .5, 1.5, .05, .15, .005,
\r
1796 .015, .0005, .0015,
\r
1798 String[] pattern = {
\r
1799 "##0%", "##0%", "##0%", "##0%", "##0%",
\r
1800 "##0%", "##0%", "##0%", "##0%", "##0%",
\r
1801 "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
\r
1802 "#,##0.00", "#,##0.000", "#,##0.000",
\r
1804 String[] expected = {
\r
1805 "2%", "1%", "2%", "2%", "1%",
\r
1806 "0%", "0%", "1%", "1%", "1%",
\r
1807 "0", "2", "0.0", "0.2", "0.00",
\r
1808 "0.02", "0.000", "0.002",
\r
1810 for (int i = 0; i < input.length; i++) {
\r
1811 DecimalFormat format = new DecimalFormat(pattern[i]);
\r
1812 String result = format.format(input[i]);
\r
1813 if (!result.equals(expected[i])) {
\r
1814 errln("FAIL: input: " + input[i] +
\r
1815 ", pattern: " + pattern[i] +
\r
1816 ", expected: " + expected[i] +
\r
1817 ", got: " + result);
\r
1820 Locale.setDefault(savedLocale);
\r
1824 class myformat implements Serializable
\r
1827 * For serialization
\r
1829 private static final long serialVersionUID = 4120813612616076506L;
\r
1830 DateFormat _dateFormat = DateFormat.getDateInstance();
\r
1832 public String Now()
\r
1834 GregorianCalendar calendar = new GregorianCalendar();
\r
1835 Date t = calendar.getTime();
\r
1836 String nowStr = _dateFormat.format(t);
\r
1841 class MyNumberFormatTest extends NumberFormat {
\r
1843 * For serialization
\r
1845 private static final long serialVersionUID = 1251303884737169952L;
\r
1846 public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
\r
1847 return new StringBuffer("");
\r
1849 public StringBuffer format(long number,StringBuffer toAppendTo, FieldPosition pos) {
\r
1850 return new StringBuffer("");
\r
1852 public Number parse(String text, ParsePosition parsePosition) {
\r
1853 return new Integer(0);
\r
1855 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
\r
1856 return new StringBuffer("");
\r
1858 public StringBuffer format(BigInteger number, StringBuffer toAppendTo, FieldPosition pos) {
\r
1859 return new StringBuffer("");
\r
1861 public StringBuffer format(com.ibm.icu.math.BigDecimal number, StringBuffer toAppendTo, FieldPosition pos) {
\r
1862 return new StringBuffer("");
\r