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