1 /*******************************************************************************
2 * Copyright (c) 2007, 2014 Association for Decentralized Information Management
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
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;
15 import java.text.DecimalFormat;
16 import java.text.DecimalFormatSymbols;
17 import java.text.NumberFormat;
18 import java.util.Locale;
21 * @author Antti Villberg
22 * @author Tuukka Lehtonen
24 public class FormattingUtil {
26 private int floatDigits;
27 private int doubleDigits;
28 private double lowLimit;
29 private double highLimit;
30 private DecimalFormatSymbols decimalFormatSymbols;
32 private DecimalFormat flow;
33 private DecimalFormat[] fmiddles;
34 private DecimalFormat fhigh;
36 private DecimalFormat dlow;
37 private DecimalFormat[] dmiddles;
38 private DecimalFormat dhigh;
40 public FormattingUtil(int floatDigits, int doubleDigits) {
41 this(floatDigits, doubleDigits, Locale.getDefault());
44 public FormattingUtil(int floatDigits, int doubleDigits, Locale locale) {
45 this(floatDigits, doubleDigits, 0.01, 1e6, locale);
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());
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);
68 private DecimalFormat createLowFormat(int digitCount) {
69 StringBuilder fmt = new StringBuilder();
71 for (int i = 0; i < digitCount; ++i)
73 //System.out.println(fmt.toString());
74 return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
77 private DecimalFormat createHighFormat(int digitCount) {
78 StringBuilder fmt = new StringBuilder();
80 if (digitCount > 3) fmt.append(".");
81 for (int i = 3; i < digitCount; ++i)
84 //System.out.println(fmt.toString());
85 return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
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)
97 if (digits > 0) fmt.append('.');
98 for (; digits > 0; --digits)
100 //System.out.println(fmt.toString());
101 middles[exp10] = new DecimalFormat(fmt.toString(), decimalFormatSymbols);
106 public String engineeringFormat(Object value) {
110 Class<?> clazz = value.getClass();
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();
120 boolean first = true;
121 for (double d : doubles) {
122 if(!first) b.append(",");
123 b.append(formatNumber(d));
128 } else if (clazz == float[].class) {
129 float[] floats = (float[])value;
130 StringBuilder b = new StringBuilder();
132 boolean first = true;
133 for (float f : floats) {
134 if(!first) b.append(",");
135 b.append(formatNumber(f));
140 } else if (clazz == int[].class) {
141 int[] ints = (int[])value;
142 StringBuilder b = new StringBuilder();
144 boolean first = true;
146 if(!first) b.append(",");
152 } else if (clazz == String.class) {
153 return (String) value;
155 return value.toString();
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)) {
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);
178 return postprocess( fhigh.format(v) );
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)) {
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);
201 return postprocess( dhigh.format(v) );
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');
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";
222 throw new NumberFormatException("Number " + num + ", instanceOf " + num.getClass().getName());
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));
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));