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