Home | History | Annotate | Download | only in format
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4  *******************************************************************************
      5  * Copyright (C) 2001-2010, International Business Machines Corporation and    *
      6  * others. All Rights Reserved.                                                *
      7  *******************************************************************************
      8  */
      9 
     10 /**
     11  * Porting From: ICU4C v1.8.1 : format : NumberFormatRoundTripTest
     12  * Source File: $ICU4CRoot/source/test/intltest/nmfmtrt.cpp
     13  **/
     14 
     15 package com.ibm.icu.dev.test.format;
     16 
     17 import java.util.Locale;
     18 import java.util.Random;
     19 
     20 import org.junit.Test;
     21 import org.junit.runner.RunWith;
     22 import org.junit.runners.JUnit4;
     23 
     24 import com.ibm.icu.dev.test.TestFmwk;
     25 import com.ibm.icu.text.DecimalFormat;
     26 import com.ibm.icu.text.NumberFormat;
     27 
     28 /**
     29  * Performs round-trip tests for NumberFormat
     30  **/
     31 @RunWith(JUnit4.class)
     32 public class NumberFormatRoundTripTest extends TestFmwk {
     33 
     34     public double MAX_ERROR = 1e-14;
     35     public double max_numeric_error = 0.0;
     36     public double min_numeric_error = 1.0;
     37     public boolean verbose = false;
     38     public boolean STRING_COMPARE = false;
     39     public boolean EXACT_NUMERIC_COMPARE = false;
     40     public boolean DEBUG = false;
     41     public boolean quick = true;
     42 
     43     @Test
     44     public void TestNumberFormatRoundTrip() {
     45 
     46         NumberFormat fmt = null;
     47 
     48         logln("Default Locale");
     49 
     50         logln("Default Number format");
     51         fmt = NumberFormat.getInstance();
     52         _test(fmt);
     53 
     54         logln("Currency Format");
     55         fmt = NumberFormat.getCurrencyInstance();
     56         _test(fmt);
     57 
     58         logln("Percent Format");
     59         fmt = NumberFormat.getPercentInstance();
     60         _test(fmt);
     61 
     62 
     63         int locCount = 0;
     64         final Locale[] loc = NumberFormat.getAvailableLocales();
     65         if(quick) {
     66             if(locCount > 5)
     67                 locCount = 5;
     68             logln("Quick mode: only _testing first 5 Locales");
     69         }
     70         for(int i = 0; i < locCount; ++i) {
     71             logln(loc[i].getDisplayName());
     72 
     73             fmt = NumberFormat.getInstance(loc[i]);
     74             _test(fmt);
     75 
     76             fmt = NumberFormat.getCurrencyInstance(loc[i]);
     77             _test(fmt);
     78 
     79             fmt = NumberFormat.getPercentInstance(loc[i]);
     80             _test(fmt);
     81         }
     82 
     83         logln("Numeric error " + min_numeric_error + " to " + max_numeric_error);
     84     }
     85 
     86     /**
     87      * Return a random value from -range..+range.
     88      */
     89     private Random random;
     90     public double randomDouble(double range) {
     91         if (random == null) {
     92             random = createRandom(); // use test framework's random seed
     93         }
     94         return  random.nextDouble() * range;
     95     }
     96 
     97     private void _test(NumberFormat fmt) {
     98 
     99         _test(fmt, Double.NaN);
    100         _test(fmt, Double.POSITIVE_INFINITY);
    101         _test(fmt, Double.NEGATIVE_INFINITY);
    102 
    103         _test(fmt, 500);
    104         _test(fmt, 0);
    105         _test(fmt, -0);
    106         _test(fmt, 0.0);
    107         double negZero = 0.0;
    108         negZero /= -1.0;
    109         _test(fmt, negZero);
    110         _test(fmt, 9223372036854775808.0d);
    111         _test(fmt, -9223372036854775809.0d);
    112         //_test(fmt, 6.936065876100493E74d);
    113 
    114     //    _test(fmt, 6.212122845281909E48d);
    115         for (int i = 0; i < 10; ++i) {
    116 
    117             _test(fmt, randomDouble(1));
    118 
    119             _test(fmt, randomDouble(10000));
    120 
    121             _test(fmt, Math.floor((randomDouble(10000))));
    122 
    123             _test(fmt, randomDouble(1e50));
    124 
    125             _test(fmt, randomDouble(1e-50));
    126 
    127             _test(fmt, randomDouble(1e100));
    128 
    129             _test(fmt, randomDouble(1e75));
    130 
    131             _test(fmt, randomDouble(1e308) / ((DecimalFormat) fmt).getMultiplier());
    132 
    133             _test(fmt, randomDouble(1e75) / ((DecimalFormat) fmt).getMultiplier());
    134 
    135             _test(fmt, randomDouble(1e65) / ((DecimalFormat) fmt).getMultiplier());
    136 
    137             _test(fmt, randomDouble(1e-292));
    138 
    139             _test(fmt, randomDouble(1e-78));
    140 
    141             _test(fmt, randomDouble(1e-323));
    142 
    143             _test(fmt, randomDouble(1e-100));
    144 
    145             _test(fmt, randomDouble(1e-78));
    146         }
    147     }
    148 
    149     private void _test(NumberFormat fmt, double value) {
    150         _test(fmt, new Double(value));
    151     }
    152 
    153     private void _test(NumberFormat fmt, long value) {
    154         _test(fmt, new Long(value));
    155     }
    156 
    157     private void _test(NumberFormat fmt, Number value) {
    158         logln("test data = " + value);
    159         fmt.setMaximumFractionDigits(999);
    160         String s, s2;
    161         if (value.getClass().getName().equalsIgnoreCase("java.lang.Double"))
    162             s = fmt.format(value.doubleValue());
    163         else
    164             s = fmt.format(value.longValue());
    165 
    166         Number n = new Double(0);
    167         boolean show = verbose;
    168         if (DEBUG)
    169             logln(
    170             /*value.getString(temp) +*/ " F> " + s);
    171         try {
    172             n = fmt.parse(s);
    173         } catch (java.text.ParseException e) {
    174             System.out.println(e);
    175         }
    176 
    177         if (DEBUG)
    178             logln(s + " P> " /*+ n.getString(temp)*/);
    179 
    180         if (value.getClass().getName().equalsIgnoreCase("java.lang.Double"))
    181             s2 = fmt.format(n.doubleValue());
    182         else
    183             s2 = fmt.format(n.longValue());
    184 
    185         if (DEBUG)
    186             logln(/*n.getString(temp) +*/ " F> " + s2);
    187 
    188         if (STRING_COMPARE) {
    189             if (!s.equals(s2)) {
    190                 errln("*** STRING ERROR \"" + s + "\" != \"" + s2 + "\"");
    191                 show = true;
    192             }
    193         }
    194 
    195         if (EXACT_NUMERIC_COMPARE) {
    196             if (value != n) {
    197                 errln("*** NUMERIC ERROR");
    198                 show = true;
    199             }
    200         } else {
    201             // Compute proportional error
    202             double error = proportionalError(value, n);
    203 
    204             if (error > MAX_ERROR) {
    205                 errln("*** NUMERIC ERROR " + error);
    206                 show = true;
    207             }
    208 
    209             if (error > max_numeric_error)
    210                 max_numeric_error = error;
    211             if (error < min_numeric_error)
    212                 min_numeric_error = error;
    213         }
    214 
    215         if (show)
    216             logln(
    217             /*value.getString(temp) +*/ value.getClass().getName() + " F> " + s + " P> " +
    218             /*n.getString(temp) +*/ n.getClass().getName() + " F> " + s2);
    219 
    220     }
    221 
    222     private double proportionalError(Number a, Number b) {
    223         double aa,bb;
    224 
    225         if(a.getClass().getName().equalsIgnoreCase("java.lang.Double"))
    226             aa = a.doubleValue();
    227         else
    228             aa = a.longValue();
    229 
    230         if(a.getClass().getName().equalsIgnoreCase("java.lang.Double"))
    231             bb = b.doubleValue();
    232         else
    233             bb = b.longValue();
    234 
    235         double error = aa - bb;
    236         if(aa != 0 && bb != 0)
    237             error /= aa;
    238 
    239         return Math.abs(error);
    240     }
    241 }
    242