1 /*
2  *******************************************************************************
3  * Copyright (C) 1996-2009, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.dev.test.format;
8 
9 import java.text.ParseException;
10 import java.util.Locale;
11 
12 import com.ibm.icu.dev.test.TestFmwk;
13 import com.ibm.icu.impl.Utility;
14 import com.ibm.icu.text.DecimalFormat;
15 import com.ibm.icu.text.DecimalFormatSymbols;
16 import com.ibm.icu.text.NumberFormat;
17 
18 /**
19  * @test
20  * General test of Big NumberFormat
21  */
22 public class BigNumberFormatTest extends TestFmwk {
23 
24     static final int ILLEGAL = -1;
25 
main(String[] args)26     public static void main(String[] args) throws Exception {
27         new BigNumberFormatTest().run(args);
28     }
29 
TestExponent()30     public void TestExponent() {
31         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
32         DecimalFormat fmt1 = new DecimalFormat("0.###E0", US);
33         DecimalFormat fmt2 = new DecimalFormat("0.###E+0", US);
34         Number n = new Long(1234);
35         expect(fmt1, n, "1.234E3");
36         expect(fmt2, n, "1.234E+3");
37         expect(fmt1, "1.234E3", n);
38         expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
39         expect(fmt2, "1.234E+3", n);
40     }
41 
42     /**
43      * Test the functioning of the secondary grouping value.
44      */
TestSecondaryGrouping()45     public void TestSecondaryGrouping() {
46         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
47         DecimalFormat f = new DecimalFormat("#,##,###", US);
48         expect(f, new Long(123456789), "12,34,56,789");
49         expectPat(f, "#,##,###");
50         f.applyPattern("#,###");
51         f.setSecondaryGroupingSize(4);
52         expect(f, new Long(123456789), "12,3456,789");
53         expectPat(f, "#,####,###");
54 
55         // On Sun JDK 1.2-1.3, the hi_IN locale uses '0' for a zero digit,
56         // but on IBM JDK 1.2-1.3, the locale uses U+0966.
57         f = (DecimalFormat) NumberFormat.getInstance(new Locale("hi", "IN"));
58         String str = transmute("1,87,65,43,210",
59                                f.getDecimalFormatSymbols().getZeroDigit());
60         expect(f, new Long(1876543210), str);
61     }
62 
expectPad(DecimalFormat fmt, String pat, int pos)63     private void expectPad(DecimalFormat fmt, String pat, int pos) {
64         expectPad(fmt, pat, pos, 0, (char)0);
65     }
66 
expectPad(DecimalFormat fmt, String pat, int pos, int width, char pad)67     private void expectPad(DecimalFormat fmt, String pat,
68                            int pos, int width, char pad) {
69         int apos = 0, awidth = 0;
70         char apad = 0;
71         try {
72             fmt.applyPattern(pat);
73             apos = fmt.getPadPosition();
74             awidth = fmt.getFormatWidth();
75             apad = fmt.getPadCharacter();
76         } catch (IllegalArgumentException e) {
77             apos = -1;
78             awidth = width;
79             apad = pad;
80         }
81         if (apos == pos && awidth == width && apad == pad) {
82             logln("Ok   \"" + pat + "\" pos=" + apos +
83                   ((pos == -1) ? "" : " width=" + awidth + " pad=" + apad));
84         } else {
85             logln("FAIL \"" + pat + "\" pos=" + apos +
86                   " width=" + awidth + " pad=" + apad +
87                   ", expected " + pos + " " + width + " " + pad);
88         }
89     }
90 
91     /**
92      */
TestPatterns()93     public void TestPatterns() {
94         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
95         DecimalFormat fmt = new DecimalFormat("#", US);
96 
97         expectPad(fmt, "*^#", DecimalFormat.PAD_BEFORE_PREFIX, 1, '^');
98         expectPad(fmt, "$*^#", DecimalFormat.PAD_AFTER_PREFIX, 2, '^');
99         expectPad(fmt, "#*^", DecimalFormat.PAD_BEFORE_SUFFIX, 1, '^');
100         expectPad(fmt, "#$*^", DecimalFormat.PAD_AFTER_SUFFIX, 2, '^');
101         expectPad(fmt, "$*^$#", ILLEGAL);
102         expectPad(fmt, "#$*^$", ILLEGAL);
103         expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat.PAD_BEFORE_SUFFIX,
104                   12, 'x');
105         expectPad(fmt, "''#0*x", DecimalFormat.PAD_BEFORE_SUFFIX,
106                   3, 'x');
107         expectPad(fmt, "'I''ll'*a###.##", DecimalFormat.PAD_AFTER_PREFIX,
108                   10, 'a');
109 
110         fmt.applyPattern("AA#,##0.00ZZ");
111         fmt.setPadCharacter('^');
112 
113         fmt.setFormatWidth(10);
114 
115         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_PREFIX);
116         expectPat(fmt, "*^AA#,##0.00ZZ");
117 
118         fmt.setPadPosition(DecimalFormat.PAD_BEFORE_SUFFIX);
119         expectPat(fmt, "AA#,##0.00*^ZZ");
120 
121         fmt.setPadPosition(DecimalFormat.PAD_AFTER_SUFFIX);
122         expectPat(fmt, "AA#,##0.00ZZ*^");
123 
124         //            12  3456789012
125         String exp = "AA*^#,##0.00ZZ";
126         fmt.setFormatWidth(12);
127         fmt.setPadPosition(DecimalFormat.PAD_AFTER_PREFIX);
128         expectPat(fmt, exp);
129 
130         fmt.setFormatWidth(13);
131         //              12  34567890123
132         expectPat(fmt, "AA*^##,##0.00ZZ");
133 
134         fmt.setFormatWidth(14);
135         //              12  345678901234
136         expectPat(fmt, "AA*^###,##0.00ZZ");
137 
138         fmt.setFormatWidth(15);
139         //              12  3456789012345
140         expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
141 
142         fmt.setFormatWidth(16);
143         //              12  34567890123456
144         expectPat(fmt, "AA*^#,###,##0.00ZZ");
145     }
146 
expectPat(DecimalFormat fmt, String exp)147     private void expectPat(DecimalFormat fmt, String exp) {
148         String pat = fmt.toPattern();
149         if (pat.equals(exp)) {
150             logln("Ok   \"" + pat + '"');
151         } else {
152             errln("FAIL \"" + pat + "\", expected \"" + exp + '"');
153         }
154     }
155 
156     /**
157      * Test the handling of the AlphaWorks BigDecimal
158      */
TestAlphaBigDecimal()159     public void TestAlphaBigDecimal() {
160         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
161         /*For ICU compatibility [Richard/GCL]*/
162         expect(NumberFormat.getScientificInstance(Locale.US),
163                new Number[] { new com.ibm.icu.math.BigDecimal("12345.678901"),
164                            },
165                "1.2345678901E4");
166         expect(new DecimalFormat("##0.####E0", US),
167                new Number[] { new com.ibm.icu.math.BigDecimal("12345.4999"),
168                               new com.ibm.icu.math.BigDecimal("12344.5001"),
169                             },
170                "12.345E3");
171         expect(new DecimalFormat("##0.####E0", US),
172                new Number[] { new com.ibm.icu.math.BigDecimal("12345.5000"),
173                               new com.ibm.icu.math.BigDecimal("12346.5000"),
174                             },
175                "12.346E3");
176     }
177 
178     /**
179      */
TestScientific()180     public void TestScientific() {
181         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
182         /*For ICU compatibility [Richard/GCL]*/
183         expect(NumberFormat.getScientificInstance(Locale.US),
184                new Number[] { new Double(12345.678901),
185                               new java.math.BigDecimal("12345.678901"),
186                             },
187                "1.2345678901E4");
188         expect(new DecimalFormat("##0.###E0", US),
189                new Double(12345),
190                "12.34E3");
191         expect(new DecimalFormat("##0.###E0", US),
192                new Double(12345.00001),
193                "12.35E3");
194         expect(new DecimalFormat("##0.####E0", US),
195                new Number[] { new Integer(12345),
196                               new Long(12345),
197                               new java.math.BigDecimal("12345.4999"),
198                               new java.math.BigDecimal("12344.5001"),
199                             },
200                "12.345E3");
201         expect(new DecimalFormat("##0.####E0", US),
202                new Number[] { new java.math.BigDecimal("12345.5000"),
203                               new java.math.BigDecimal("12346.5000"),
204                             },
205                "12.346E3");
206         /*For ICU compatibility [Richard/GCL]*/
207         expect(NumberFormat.getScientificInstance(Locale.FRANCE),
208                new Double(12345.678901),
209                "1,2345678901E4");
210         expect(new DecimalFormat("##0.####E0", US),
211                new Double(789.12345e-9),
212                "789.12E-9");
213         expect(new DecimalFormat("##0.####E0", US),
214                new Double(780.e-9),
215                "780E-9");
216         expect(new DecimalFormat(".###E0", US),
217                new Double(45678),
218                ".457E5");
219         expect(new DecimalFormat(".###E0", US),
220                new Long(0),
221                ".0E0");
222         expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
223                                      new DecimalFormat("##E0", US),
224                                      new DecimalFormat("####E0", US),
225                                      new DecimalFormat("0E0", US),
226                                      new DecimalFormat("00E0", US),
227                                      new DecimalFormat("000E0", US),
228                                    },
229                new Long(45678000),
230                new String[] { "4.5678E7",
231                               "45.678E6",
232                               "4567.8E4",
233                               "5E7",
234                               "46E6",
235                               "457E5",
236                             }
237                );
238         expect(new DecimalFormat("###E0", US),
239                new Object[] { new Double(0.0000123), "12.3E-6",
240                               new Double(0.000123), "123E-6",
241                               new java.math.BigDecimal("0.00123"), "1.23E-3", // Cafe VM messes up Double(0.00123)
242                               new Double(0.0123), "12.3E-3",
243                               new Double(0.123), "123E-3",
244                               new Double(1.23), "1.23E0",
245                               new Double(12.3), "12.3E0",
246                               new Double(123), "123E0",
247                               new Double(1230), "1.23E3",
248                              });
249         expect(new DecimalFormat("0.#E+00", US),
250                new Object[] { new Double(0.00012), "1.2E-04",
251                               new Long(12000),     "1.2E+04",
252                              });
253     }
254 
255     /**
256      */
TestPad()257     public void TestPad() {
258         DecimalFormatSymbols US = new DecimalFormatSymbols(Locale.US);
259         expect(new DecimalFormat("*^##.##", US),
260                new Object[] { new Long(0),      "^^^^0",
261                               new Double(-1.3), "^-1.3",
262                             }
263                );
264         expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US),
265                new Object[] { new Long(0),       "0.0E0______ g-m/s^2",
266                               new Double(1.0/3), "333.333E-3_ g-m/s^2",
267                             }
268                );
269         expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US),
270                new Object[] { new Long(0),       "0.0______ g-m/s^2",
271                               new Double(1.0/3), "0.33333__ g-m/s^2",
272                             }
273                );
274         expect(new DecimalFormat("*x#,###,###,##0.00;*x(#,###,###,##0.00)", US),
275                new Object[] {
276                    new Long(-100),        "xxxxxxxx(100.00)",
277                    new Long(-1000),       "xxxxxx(1,000.00)",
278                    new Long(-1000000),    "xx(1,000,000.00)",
279                    new Long(-1000000000), "(1,000,000,000.00)",
280                });
281     }
282 
expect(NumberFormat fmt, Object[] data)283     private void expect(NumberFormat fmt, Object[] data) {
284         for (int i=0; i<data.length; i+=2) {
285             expect(fmt, (Number) data[i], (String) data[i+1]);
286         }
287     }
288 
expect(Object fmto, Object numo, Object expo)289     private void expect(Object fmto, Object numo, Object expo) {
290         NumberFormat fmt = null, fmts[] = null;
291         Number num = null, nums[] = null;
292         String exp = null, exps[] = null;
293         if (fmto instanceof NumberFormat[]) {
294             fmts = (NumberFormat[]) fmto;
295         } else {
296             fmt = (NumberFormat) fmto;
297         }
298         if (numo instanceof Number[]) {
299             nums = (Number[]) numo;
300         } else {
301             num = (Number) numo;
302         }
303         if (expo instanceof String[]) {
304             exps = (String[]) expo;
305         } else {
306             exp = (String) expo;
307         }
308         int n = 1;
309         if (fmts != null) {
310             n = Math.max(n, fmts.length);
311         }
312         if (nums != null) {
313             n = Math.max(n, nums.length);
314         }
315         if (exps != null) {
316             n = Math.max(n, exps.length);
317         }
318         for (int i=0; i<n; ++i) {
319             expect(fmts == null ? fmt : fmts[i],
320                    nums == null ? num : nums[i],
321                    exps == null ? exp : exps[i]);
322         }
323     }
324 
showNumber(Number n)325     private static String showNumber(Number n) {
326         String cls = n.getClass().getName();
327         if (!(n instanceof com.ibm.icu.math.BigDecimal
328               || n instanceof java.math.BigDecimal)) {
329             int i = cls.lastIndexOf('.');
330             cls = cls.substring(i+1);
331         }
332         return n.toString() + " (" + cls + ')';
333     }
334 
expect(NumberFormat fmt, Number n, String exp)335     private void expect(NumberFormat fmt, Number n, String exp) {
336         String saw = fmt.format(n);
337         String pat = ((DecimalFormat) fmt).toPattern();
338         if (saw.equals(exp)) {
339             logln("Ok   " + showNumber(n) + " x " +
340                   pat + " = " +
341                   Utility.escape(saw));
342         } else {
343             errln("FAIL " + showNumber(n) + " x " +
344                   pat + " = \"" +
345                   Utility.escape(saw) + ", expected " + Utility.escape(exp));
346         }
347     }
348 
expect(NumberFormat fmt, String str, Number exp)349     private void expect(NumberFormat fmt, String str, Number exp) {
350         Number saw = null;
351         try {
352             saw = fmt.parse(str);
353         } catch (ParseException e) {
354             saw = null;
355         }
356         String pat = ((DecimalFormat) fmt).toPattern();
357         if (saw.equals(exp)) {
358             logln("Ok   \"" + str + "\" x " +
359                   pat + " = " +
360                   showNumber(saw));
361         } else {
362             errln("FAIL \"" + str + "\" x " +
363                   pat + " = " +
364                   showNumber(saw) + ", expected " + showNumber(exp));
365         }
366     }
367 
368     /**
369      * Given a string composed of [0-9] and other chars, convert the
370      * [0-9] chars to be offsets 0..9 from 'zero'.
371      */
transmute(String str, char zero)372     private static String transmute(String str, char zero) {
373         StringBuffer buf = new StringBuffer();
374         for (int i=0; i<str.length(); ++i) {
375             char c = str.charAt(i);
376             if (c >= '0' && c <= '9') {
377                 c = (char) (c - '0' + zero);
378             }
379             buf.append(c);
380         }
381         return buf.toString();
382     }
383 
Test4161100()384     public void Test4161100() {
385         NumberFormat f = NumberFormat.getInstance();
386         f.setMinimumFractionDigits(1);
387         f.setMaximumFractionDigits(1);
388         double a = -0.09;
389         String s = f.format(a);
390         logln(a + " x " +
391               ((DecimalFormat) f).toPattern() + " = " +
392               s);
393         if (!s.equals("-0.1")) {
394             errln("FAIL");
395         }
396     }
397 
TestBigDecimalJ28()398     public void TestBigDecimalJ28() {
399         String[] DATA = {
400             "1", "1E0",
401             "-1", "-1E0",
402             "0", "0E0",
403             "12e34", "1.2E35",
404             "-12.3e-45", "-1.23E-44",
405             "0.73e-7", "7.3E-8",
406         };
407         NumberFormat fmt = NumberFormat.getScientificInstance(Locale.US);
408         logln("Pattern: " + ((DecimalFormat)fmt).toPattern());
409         for (int i=0; i<DATA.length; i+=2) {
410             String input = DATA[i];
411             String exp = DATA[i+1];
412             com.ibm.icu.math.BigDecimal bd = new com.ibm.icu.math.BigDecimal(input);
413             String output = fmt.format(bd);
414             if (output.equals(exp)) {
415                 logln("input=" + input + " num=" + bd + " output=" + output);
416             } else {
417                 errln("FAIL: input=" + input + " num=" + bd + " output=" + output +
418                       " expected=" + exp);
419             }
420         }
421     }
TestBigDecimalRounding()422     public void TestBigDecimalRounding() {
423         // jb 3657
424         java.text.DecimalFormat jdkFormat=new java.text.DecimalFormat("###,###,###,##0");
425         com.ibm.icu.text.DecimalFormat icuFormat=new com.ibm.icu.text.DecimalFormat("###,###,###,##0");
426         String[] values = {
427             "-1.74", "-1.24", "-0.74", "-0.24", "0.24", "0.74", "1.24", "1.74"
428         };
429         for (int i = 0; i < values.length; ++i) {
430             String val = values[i];
431             java.math.BigDecimal bd = new java.math.BigDecimal(val);
432             String jdk = jdkFormat.format(bd);
433             String icu = icuFormat.format(bd);
434             logln("Format of BigDecimal " + val + " by JDK is " + jdk);
435             logln("Format of BigDecimal " + val + " by ICU is " + icu);
436             if (!jdk.equals(icu)) {
437                 errln("BigDecimal jdk: " + jdk + " != icu: " + icu);
438             }
439 
440             double d = bd.doubleValue();
441             jdk = jdkFormat.format(d);
442             icu = icuFormat.format(d);
443             logln("Format of double " + val + " by JDK is " + jdk);
444             logln("Format of double " + val + " by ICU is " + icu);
445             if (!jdk.equals(icu)) {
446                 errln("double jdk: " + jdk + " != icu: " + icu);
447             }
448         }
449     }
450 }
451