]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils/src/org/simantics/utils/format/FormattingUtil.java
ab88bcaf4cd889fadf99cb14337dcc04ab2e0c70
[simantics/platform.git] / bundles / org.simantics.utils / src / org / simantics / utils / format / FormattingUtil.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2014 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum Oy - improved output precision control
12  *******************************************************************************/
13 package org.simantics.utils.format;
14
15 import java.text.DecimalFormat;
16 import java.text.DecimalFormatSymbols;
17 import java.text.NumberFormat;
18 import java.util.Locale;
19
20 /**
21  * @author Antti Villberg
22  * @author Tuukka Lehtonen
23  */
24 public class FormattingUtil {
25
26     private int floatDigits;
27     private int doubleDigits;
28     private double lowLimit;
29     private double highLimit;
30     private DecimalFormatSymbols decimalFormatSymbols;
31
32     private DecimalFormat flow;
33     private DecimalFormat[] fmiddles;
34     private DecimalFormat fhigh;
35
36     private DecimalFormat dlow;
37     private DecimalFormat[] dmiddles;
38     private DecimalFormat dhigh;
39
40     public FormattingUtil(int floatDigits, int doubleDigits) {
41         this(floatDigits, doubleDigits, Locale.getDefault());
42     }
43     
44     public FormattingUtil(int floatDigits, int doubleDigits, Locale locale) {
45         this(floatDigits, doubleDigits, 0.01, 1e6, locale);
46     }
47
48     public FormattingUtil(int floatDigits, int doubleDigits, double lowLimit, double highLimit, Locale locale) {
49         this.floatDigits = floatDigits;
50         this.doubleDigits = doubleDigits;
51         this.lowLimit = lowLimit;
52         this.highLimit = highLimit;
53         this.decimalFormatSymbols = DecimalFormatSymbols.getInstance(locale != null ? locale : Locale.getDefault());
54         initFormats();
55     }
56
57     private void initFormats() {
58         this.flow = createLowFormat(floatDigits);
59         double exp = Math.log10(highLimit);
60         int formatCount = Math.max(1, (int) Math.ceil(exp));
61         this.fmiddles = createMiddleFormats(formatCount, floatDigits);
62         this.fhigh = createHighFormat(floatDigits);
63         this.dlow = createLowFormat(doubleDigits);
64         this.dmiddles = createMiddleFormats(formatCount, doubleDigits);
65         this.dhigh = createHighFormat(doubleDigits);
66     }
67
68     private DecimalFormat createLowFormat(int digitCount) {
69         StringBuilder fmt = new StringBuilder();
70         fmt.append("0.");
71         for (int i = 0; i < digitCount; ++i)
72             fmt.append('#');
73         //System.out.println(fmt.toString());
74         return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
75     }
76
77     private DecimalFormat createHighFormat(int digitCount) {
78         StringBuilder fmt = new StringBuilder();
79         fmt.append("##0");
80         if (digitCount > 3) fmt.append(".");
81         for (int i = 3; i < digitCount; ++i)
82             fmt.append('#');
83         fmt.append("E0");
84         //System.out.println(fmt.toString());
85         return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
86     }
87
88     private DecimalFormat[] createMiddleFormats(int formatCount, int digitCount) {
89         DecimalFormat[] middles = new DecimalFormat[formatCount];
90         for (int exp10 = 0; exp10 < formatCount; ++exp10) {
91             StringBuilder fmt = new StringBuilder();
92             int digits = digitCount;
93             for (int i = 0; i < exp10 && digits > 1; ++i, --digits)
94                 fmt.append('#');
95             fmt.append('0');
96             --digits;
97             if (digits > 0) fmt.append('.');
98             for (; digits > 0; --digits)
99                 fmt.append('#');
100             //System.out.println(fmt.toString());
101             middles[exp10] = new DecimalFormat(fmt.toString(), decimalFormatSymbols);
102         }
103         return middles;
104     }
105
106     public String engineeringFormat(Object value) {
107         if (value == null)
108             return "";
109
110         Class<?> clazz = value.getClass();
111
112         if (clazz == Double.class) {
113             return formatNumber((Double) value);
114         } else if (clazz == Float.class) {
115             return formatNumber((Float)value);
116         } else if (clazz == double[].class) {
117             double[] doubles = (double[])value;
118             StringBuilder b = new StringBuilder();
119             b.append("[");
120             boolean first = true;
121             for (double d : doubles) {
122                 if(!first) b.append(",");
123                 b.append(formatNumber(d));
124                 first = false;
125             }
126             b.append("]");
127             return b.toString();
128         } else if (clazz == float[].class) {
129             float[] floats = (float[])value;
130             StringBuilder b = new StringBuilder();
131             b.append("[");
132             boolean first = true;
133             for (float f : floats) {
134                 if(!first) b.append(",");
135                 b.append(formatNumber(f));
136                 first = false;
137             }
138             b.append("]");
139             return b.toString();
140         } else if (clazz == int[].class) {
141             int[] ints = (int[])value;
142             StringBuilder b = new StringBuilder();
143             b.append("[");
144             boolean first = true;
145             for (int d : ints) {
146                 if(!first) b.append(",");
147                 b.append(d);
148                 first = false;
149             }
150             b.append("]");
151             return b.toString();
152         } else if (clazz == String.class) {
153             return (String) value;
154         } else {
155             return value.toString();
156         }
157     }
158
159     public String formatNumber(float v) {
160         if (Float.isInfinite(v)) {
161             return (v == Float.POSITIVE_INFINITY) ? "\u221E" : "-\u221E";
162         } else if (Float.isNaN(v)) {
163             return "NaN";
164         } else {
165             float abs = Math.abs(v);
166             if (abs < 1.0f && abs >= (float)lowLimit) {
167                 return flow.format(v);
168             } else if (abs >= 1.0f && abs < (float)highLimit) {
169                 double exp = Math.log10(abs);
170                 int expi = (int) Math.floor(exp);
171 //                System.out.println("format(" + v + ")");
172 //                System.out.println("exp: " + exp);
173 //                System.out.println("expi: " + expi);
174                 if (expi < fmiddles.length) { 
175                     return fmiddles[expi].format(v);
176                 }
177             }
178             return postprocess( fhigh.format(v) );
179         }
180     }
181
182     public String formatNumber(double v) {
183         if (Double.isInfinite(v)) {
184             return (v == Double.POSITIVE_INFINITY) ? "\u221E" : "-\u221E";
185         } else if (Double.isNaN(v)) {
186             return "NaN";
187         } else {
188             double abs = Math.abs(v);
189             if (abs < 1.0 && abs >= lowLimit) {
190                 return dlow.format(v);
191             } else if (abs >= 1.0 && abs < highLimit) {
192                 double exp = Math.log10(abs);
193                 int expi = (int) Math.floor(exp);
194 //                System.out.println("format(" + v + ")");
195 //                System.out.println("exp: " + exp);
196 //                System.out.println("expi: " + expi);
197                 if (expi < dmiddles.length) { 
198                     return dmiddles[expi].format(v);
199                 }
200             }
201             return postprocess( dhigh.format(v) );
202         }
203     }
204
205     private static String postprocess(String s) {
206         if (s.endsWith("E0"))
207             return s.substring(0, s.length() - 2);
208         return s.replace('E', 'e');
209     }
210
211     public static String formatNumberLocale(Object num, int minPrecision, int maxPrecision, String languageTag) {
212         NumberFormat format = NumberFormat.getNumberInstance(Locale.forLanguageTag(languageTag));
213         format.setMaximumFractionDigits(maxPrecision);
214         format.setMinimumFractionDigits(minPrecision);
215         if (num instanceof java.lang.Number) {
216                 double doubleValue = ((java.lang.Number)num).doubleValue();
217                 if(Double.isFinite(doubleValue))
218                         return format.format(doubleValue);
219                 else if(Double.isNaN(doubleValue)) return "NaN";
220                 else if(Double.isInfinite(doubleValue)) return "\u221e";
221         } 
222         throw new NumberFormatException("Number " + num + ", instanceOf " + num.getClass().getName());
223     }    
224     
225     public static void main(String[] args) {
226         FormattingUtil fu = new FormattingUtil(7, 15);
227         System.out.println("=== DOUBLE ===");
228         System.out.println(fu.formatNumber(123e-3));
229         System.out.println(fu.formatNumber(-123e-3));
230         System.out.println(fu.formatNumber(Double.POSITIVE_INFINITY));
231         System.out.println(fu.formatNumber(Double.NEGATIVE_INFINITY));
232         System.out.println(fu.formatNumber(Double.NaN));
233         System.out.println(fu.formatNumber(0));
234         System.out.println(fu.formatNumber(0.25));
235         System.out.println(fu.formatNumber(0.1));
236         System.out.println(fu.formatNumber(1));
237         System.out.println(fu.formatNumber(-0.25));
238         System.out.println(fu.formatNumber(-0.1));
239         System.out.println(fu.formatNumber(-1));
240         System.out.println(fu.formatNumber(0.9999));
241         System.out.println(fu.formatNumber(0.0999999999999999999));
242         System.out.println(fu.formatNumber(0.0099999999999999999999));
243         System.out.println(fu.formatNumber(0.004541234));
244         System.out.println(fu.formatNumber(0.00099999999999999999999));
245         System.out.println(fu.formatNumber(0.000099999999999999999999));
246         System.out.println(fu.formatNumber(0.0000099999999999999999999));
247         System.out.println(fu.formatNumber(0.00000099999999999999999999));
248         System.out.println(fu.formatNumber(-0.9999));
249         System.out.println(fu.formatNumber(-0.0999999999999999999));
250         System.out.println(fu.formatNumber(-0.0099999999999999999999));
251         System.out.println(fu.formatNumber(-0.00099999999999999999999));
252         System.out.println(fu.formatNumber(-0.000099999999999999999999));
253         System.out.println(fu.formatNumber(1.234567891));
254         System.out.println(fu.formatNumber(12.34567891));
255         System.out.println(fu.formatNumber(123.4567891));
256         System.out.println(fu.formatNumber(1234.567891));
257         System.out.println(fu.formatNumber(12345.67891));
258         System.out.println(fu.formatNumber(123456.7891));
259         System.out.println(fu.formatNumber(1234567.891));
260         System.out.println(fu.formatNumber(1234567.8912345678));
261         System.out.println(fu.formatNumber(12345678.912345678));
262         System.out.println(fu.formatNumber(123456789.12345678));
263         System.out.println(fu.formatNumber(1234567891.2345678));
264         System.out.println(fu.formatNumber(12345678912.345678));
265         System.out.println(fu.formatNumber(100.0000000000000));
266         System.out.println(fu.formatNumber(100000.0000000000));
267         System.out.println(fu.formatNumber(1000000000.000000));
268         System.out.println(fu.formatNumber(100000000000.0000));
269         System.out.println(fu.formatNumber(10000000000000.00));
270         System.out.println(fu.formatNumber(999999.99999999999999));
271         System.out.println(fu.formatNumber(999999.9999999999999));
272         System.out.println(fu.formatNumber(999999.999999999999));
273         System.out.println(fu.formatNumber(999999.99999999999));
274         System.out.println(fu.formatNumber(999999.9999999999));
275         System.out.println(fu.formatNumber(999999.999999999));
276         System.out.println(fu.formatNumber(999999.99999999));
277         System.out.println(fu.formatNumber(999999.9999999));
278         System.out.println(fu.formatNumber(999999.999999));
279         System.out.println(fu.formatNumber(999999.99999));
280         System.out.println(fu.formatNumber(999999.9999));
281         System.out.println(fu.formatNumber(999999.999));
282         System.out.println(fu.formatNumber(999999.99));
283         System.out.println(fu.formatNumber(999999.9));
284         System.out.println(fu.formatNumber(999999));
285
286         System.out.println("=== FLOAT ===");
287         System.out.println(fu.formatNumber(123e-3f));
288         System.out.println(fu.formatNumber(-123e-3f));
289         System.out.println(fu.formatNumber(Float.POSITIVE_INFINITY));
290         System.out.println(fu.formatNumber(Float.NEGATIVE_INFINITY));
291         System.out.println(fu.formatNumber(Float.NaN));
292         System.out.println(fu.formatNumber(0f));
293         System.out.println(fu.formatNumber(0.25f));
294         System.out.println(fu.formatNumber(0.1f));
295         System.out.println(fu.formatNumber(1f));
296         System.out.println(fu.formatNumber(-0.25f));
297         System.out.println(fu.formatNumber(-0.1f));
298         System.out.println(fu.formatNumber(-1f));
299         System.out.println(fu.formatNumber(0.9999f));
300         System.out.println(fu.formatNumber(0.0999999999999999999f));
301         System.out.println(fu.formatNumber(0.0099999999999999999999f));
302         System.out.println(fu.formatNumber(0.004541234f));
303         System.out.println(fu.formatNumber(0.00099999999999999999999f));
304         System.out.println(fu.formatNumber(0.000099999999999999999999f));
305         System.out.println(fu.formatNumber(0.0000099999999999999999999f));
306         System.out.println(fu.formatNumber(0.00000099999999999999999999f));
307         System.out.println(fu.formatNumber(-0.9999f));
308         System.out.println(fu.formatNumber(-0.0999999999999999999f));
309         System.out.println(fu.formatNumber(-0.0099999999999999999999f));
310         System.out.println(fu.formatNumber(-0.00099999999999999999999f));
311         System.out.println(fu.formatNumber(-0.000099999999999999999999f));
312         System.out.println(fu.formatNumber(1.234567891f));
313         System.out.println(fu.formatNumber(12.34567891f));
314         System.out.println(fu.formatNumber(123.4567891f));
315         System.out.println(fu.formatNumber(1234.567891f));
316         System.out.println(fu.formatNumber(12345.67891f));
317         System.out.println(fu.formatNumber(123456.7891f));
318         System.out.println(fu.formatNumber(1234567.891f));
319         System.out.println(fu.formatNumber(1234567.8912345678f));
320         System.out.println(fu.formatNumber(12345678.912345678f));
321         System.out.println(fu.formatNumber(123456789.12345678f));
322         System.out.println(fu.formatNumber(1234567891.2345678f));
323         System.out.println(fu.formatNumber(12345678912.345678f));
324         System.out.println(fu.formatNumber(100.0000000000000f));
325         System.out.println(fu.formatNumber(100000.0000000000f));
326         System.out.println(fu.formatNumber(1000000000.000000f));
327         System.out.println(fu.formatNumber(100000000000.0000f));
328         System.out.println(fu.formatNumber(10000000000000.00f));
329         System.out.println(fu.formatNumber(999999.99999999999999f));
330         System.out.println(fu.formatNumber(999999.9999999999999f));
331         System.out.println(fu.formatNumber(999999.999999999999f));
332         System.out.println(fu.formatNumber(999999.99999999999f));
333         System.out.println(fu.formatNumber(999999.9999999999f));
334         System.out.println(fu.formatNumber(999999.999999999f));
335         System.out.println(fu.formatNumber(999999.99999999f));
336         System.out.println(fu.formatNumber(999999.9999999f));
337         System.out.println(fu.formatNumber(999999.999999f));
338         System.out.println(fu.formatNumber(999999.99999f));
339         System.out.println(fu.formatNumber(999999.9999f));
340         System.out.println(fu.formatNumber(999999.999f));
341         System.out.println(fu.formatNumber(999999.99f));
342         System.out.println(fu.formatNumber(999999.9f));
343         System.out.println(fu.formatNumber(999999f));
344     }
345
346 }