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
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
15 import java.text.DecimalFormat;
\r
16 import java.text.DecimalFormatSymbols;
\r
17 import java.text.NumberFormat;
\r
18 import java.util.Locale;
\r
21 * @author Antti Villberg
\r
22 * @author Tuukka Lehtonen
\r
24 public class FormattingUtil {
\r
26 private int floatDigits;
\r
27 private int doubleDigits;
\r
28 private DecimalFormatSymbols decimalFormatSymbols;
\r
30 private DecimalFormat flow;
\r
31 private DecimalFormat[] fmiddles;
\r
32 private DecimalFormat fhigh;
\r
34 private DecimalFormat dlow;
\r
35 private DecimalFormat[] dmiddles;
\r
36 private DecimalFormat dhigh;
\r
38 public FormattingUtil(int floatDigits, int doubleDigits) {
\r
39 this(floatDigits, doubleDigits, Locale.getDefault());
\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
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
58 private DecimalFormat createLowFormat(int digitCount) {
\r
59 StringBuilder fmt = new StringBuilder();
\r
61 for (int i = 0; i < digitCount; ++i)
\r
63 //System.out.println(fmt.toString());
\r
64 return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
\r
67 private DecimalFormat createHighFormat(int digitCount) {
\r
68 StringBuilder fmt = new StringBuilder();
\r
70 for (int i = 3; i < digitCount; ++i)
\r
73 //System.out.println(fmt.toString());
\r
74 return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
\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
87 for (; digits > 0; --digits)
\r
89 //System.out.println(fmt.toString());
\r
90 middles[exp10] = new DecimalFormat(fmt.toString(), DecimalFormatSymbols.getInstance(Locale.US));
\r
95 public String engineeringFormat(Object value) {
\r
99 Class<?> clazz = value.getClass();
\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
109 boolean first = true;
\r
110 for (double d : doubles) {
\r
111 if(!first) b.append(",");
\r
112 b.append(formatNumber(d));
\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
121 boolean first = true;
\r
122 for (float f : floats) {
\r
123 if(!first) b.append(",");
\r
124 b.append(formatNumber(f));
\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
133 boolean first = true;
\r
134 for (int d : ints) {
\r
135 if(!first) b.append(",");
\r
140 return b.toString();
\r
141 } else if (clazz == String.class) {
\r
142 return (String) value;
\r
144 return value.toString();
\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
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
167 return postprocess( fhigh.format(v) );
\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
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
190 return postprocess( dhigh.format(v) );
\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
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
211 throw new NumberFormatException("Number " + num + ", instanceOf " + num.getClass().getName());
\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
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