Added trailing zero visibility control for FormattingUtil 90/2490/1
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 23 Nov 2018 08:55:50 +0000 (10:55 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 23 Nov 2018 08:55:50 +0000 (10:55 +0200)
Also fixed some bugs in constructing the formatters with designated
smaller amount of significant digits.

High-value formatter selection was made a bit more complex by the
trailing zeroes option.

gitlab #213

Change-Id: I9e1b159940d4058a21d6cad5080892b6e1ed2d6c

bundles/org.simantics.utils/src/org/simantics/utils/format/FormattingUtil.java

index ab88bcaf4cd889fadf99cb14337dcc04ab2e0c70..8b8b40dc2d8c7d74c450e6fea2581217179d20c5 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2014 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2018 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -8,7 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
- *     Semantum Oy - improved output precision control
+ *     Semantum Oy - improved output precision control, trailing zero control
  *******************************************************************************/
 package org.simantics.utils.format;
 
@@ -27,61 +27,66 @@ public class FormattingUtil {
     private int doubleDigits;
     private double lowLimit;
     private double highLimit;
+    private boolean trailingZeroes;
     private DecimalFormatSymbols decimalFormatSymbols;
 
     private DecimalFormat flow;
     private DecimalFormat[] fmiddles;
-    private DecimalFormat fhigh;
+    private DecimalFormat[] fhighs;
 
     private DecimalFormat dlow;
     private DecimalFormat[] dmiddles;
-    private DecimalFormat dhigh;
+    private DecimalFormat[] dhighs;
 
     public FormattingUtil(int floatDigits, int doubleDigits) {
         this(floatDigits, doubleDigits, Locale.getDefault());
     }
-    
+
+    public FormattingUtil(int floatDigits, int doubleDigits, boolean addTrailingZeroes) {
+        this(floatDigits, doubleDigits, Locale.getDefault(), addTrailingZeroes);
+    }
+
     public FormattingUtil(int floatDigits, int doubleDigits, Locale locale) {
-        this(floatDigits, doubleDigits, 0.01, 1e6, locale);
+        this(floatDigits, doubleDigits, 0.01, 1e6, locale, false);
     }
 
     public FormattingUtil(int floatDigits, int doubleDigits, double lowLimit, double highLimit, Locale locale) {
+        this(floatDigits, doubleDigits, lowLimit, highLimit, locale, false);
+    }
+
+    public FormattingUtil(int floatDigits, int doubleDigits, Locale locale, boolean addTrailingZeroes) {
+        this(floatDigits, doubleDigits, 0.01, 1e6, locale, addTrailingZeroes);
+    }
+
+    public FormattingUtil(int floatDigits, int doubleDigits, double lowLimit, double highLimit, Locale locale, boolean addTrailingZeroes) {
        this.floatDigits = floatDigits;
         this.doubleDigits = doubleDigits;
         this.lowLimit = lowLimit;
         this.highLimit = highLimit;
+        this.trailingZeroes = addTrailingZeroes;
         this.decimalFormatSymbols = DecimalFormatSymbols.getInstance(locale != null ? locale : Locale.getDefault());
         initFormats();
     }
 
     private void initFormats() {
-        this.flow = createLowFormat(floatDigits);
         double exp = Math.log10(highLimit);
         int formatCount = Math.max(1, (int) Math.ceil(exp));
+        //System.out.println("initFormats(FLOAT; " + floatDigits + ")");
+        this.flow = createLowFormat(floatDigits);
         this.fmiddles = createMiddleFormats(formatCount, floatDigits);
-        this.fhigh = createHighFormat(floatDigits);
+        this.fhighs = createHighFormats(floatDigits);
+        //System.out.println("initFormats(DOUBLE; " + doubleDigits + ")");
         this.dlow = createLowFormat(doubleDigits);
         this.dmiddles = createMiddleFormats(formatCount, doubleDigits);
-        this.dhigh = createHighFormat(doubleDigits);
+        this.dhighs = createHighFormats(doubleDigits);
     }
 
     private DecimalFormat createLowFormat(int digitCount) {
         StringBuilder fmt = new StringBuilder();
         fmt.append("0.");
         for (int i = 0; i < digitCount; ++i)
-            fmt.append('#');
-        //System.out.println(fmt.toString());
-        return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
-    }
-
-    private DecimalFormat createHighFormat(int digitCount) {
-        StringBuilder fmt = new StringBuilder();
-        fmt.append("##0");
-        if (digitCount > 3) fmt.append(".");
-        for (int i = 3; i < digitCount; ++i)
-            fmt.append('#');
-        fmt.append("E0");
-        //System.out.println(fmt.toString());
+            fmt.append(trailingZeroes ? '0' : '#');
+        //System.out.println("lowFormat(" + digitCount + "): " + fmt);
         return new DecimalFormat(fmt.toString(), decimalFormatSymbols);
     }
 
@@ -90,19 +95,45 @@ public class FormattingUtil {
         for (int exp10 = 0; exp10 < formatCount; ++exp10) {
             StringBuilder fmt = new StringBuilder();
             int digits = digitCount;
-            for (int i = 0; i < exp10 && digits > 1; ++i, --digits)
-                fmt.append('#');
-            fmt.append('0');
-            --digits;
-            if (digits > 0) fmt.append('.');
-            for (; digits > 0; --digits)
-                fmt.append('#');
-            //System.out.println(fmt.toString());
+            int i = 0;
+            for (; i <= exp10 && digits > 0; ++i, --digits)
+                fmt.append('0');
+            if (digits <= 0) {
+                if (i <= exp10)
+                    fmt.append("E0");
+            } else {
+                if (digits > 0) fmt.append('.');
+                for (; digits > 0; --digits)
+                    fmt.append(trailingZeroes ? '0' : '#');
+            }
+            //System.out.println("middleFormat(" + exp10 + "; " + digitCount + "): " + fmt);
             middles[exp10] = new DecimalFormat(fmt.toString(), decimalFormatSymbols);
         }
         return middles;
     }
 
+    private DecimalFormat[] createHighFormats(int digitCount) {
+        // [0] = for formatting 1.234567e{6,9,...}
+        // [1] = for formatting 12.34567e{6,9,...}
+        // [2] = for formatting 123.4567e{6,9,...}
+        DecimalFormat[] highs = new DecimalFormat[3];
+        for (int exp10 = 0; exp10 < 3; ++exp10) {
+            StringBuilder fmt = new StringBuilder();
+            int digits = digitCount;
+            for (int i = 0; i <= exp10 && digits > 0; ++i, --digits)
+               fmt.append('0');
+            if (digits > 0) {
+                fmt.append(".");
+                for (; digits > 0; --digits)
+                    fmt.append(trailingZeroes ? '0' : '#');
+            }
+            fmt.append("E0");
+            //System.out.println("highFormat(" + exp10  + "; " + digitCount + "): " + fmt);
+            highs[exp10] = new DecimalFormat(fmt.toString(), decimalFormatSymbols);
+        }
+        return highs;
+    }
+
     public String engineeringFormat(Object value) {
         if (value == null)
             return "";
@@ -156,6 +187,26 @@ public class FormattingUtil {
         }
     }
 
+    private static int highFormatterIndex(int exp10) {
+        return exp10 < 0 ? (exp10 % 3 + 3) % 3 : exp10 % 3;
+    }
+
+    private static int highFormatterIndex(float absValue) {
+        return highFormatterIndex((int) Math.floor((float) Math.log10(absValue)));
+    }
+
+    private static int highFormatterIndex(double absValue) {
+       return highFormatterIndex((int) Math.floor(Math.log10(absValue)));
+    }
+
+    private static int middleFormatterIndex(float absValue) {
+        return (int) Math.floor((float) Math.log10(absValue));
+    }
+    
+    private static int middleFormatterIndex(double absValue) {
+        return (int) Math.floor(Math.log10(absValue));
+    }
+    
     public String formatNumber(float v) {
         if (Float.isInfinite(v)) {
             return (v == Float.POSITIVE_INFINITY) ? "\u221E" : "-\u221E";
@@ -163,19 +214,14 @@ public class FormattingUtil {
             return "NaN";
         } else {
             float abs = Math.abs(v);
-            if (abs < 1.0f && abs >= (float)lowLimit) {
+            if ((abs < 1.0f && abs >= (float)lowLimit) || abs == 0.0f) {
                 return flow.format(v);
             } else if (abs >= 1.0f && abs < (float)highLimit) {
-                double exp = Math.log10(abs);
-                int expi = (int) Math.floor(exp);
-//                System.out.println("format(" + v + ")");
-//                System.out.println("exp: " + exp);
-//                System.out.println("expi: " + expi);
-                if (expi < fmiddles.length) { 
+                int expi = middleFormatterIndex(abs);
+                if (expi < fmiddles.length) 
                     return fmiddles[expi].format(v);
-                }
             }
-            return postprocess( fhigh.format(v) );
+            return postprocess( fhighs[ highFormatterIndex(abs) ].format(v) );
         }
     }
 
@@ -186,19 +232,14 @@ public class FormattingUtil {
             return "NaN";
         } else {
             double abs = Math.abs(v);
-            if (abs < 1.0 && abs >= lowLimit) {
+            if ((abs < 1.0 && abs >= lowLimit) || abs == 0.0) {
                 return dlow.format(v);
             } else if (abs >= 1.0 && abs < highLimit) {
-                double exp = Math.log10(abs);
-                int expi = (int) Math.floor(exp);
-//                System.out.println("format(" + v + ")");
-//                System.out.println("exp: " + exp);
-//                System.out.println("expi: " + expi);
-                if (expi < dmiddles.length) { 
+                int expi = middleFormatterIndex(abs);
+                if (expi < dmiddles.length) 
                     return dmiddles[expi].format(v);
-                }
             }
-            return postprocess( dhigh.format(v) );
+            return postprocess( dhighs[ highFormatterIndex(abs) ].format(v) );
         }
     }
 
@@ -221,22 +262,22 @@ public class FormattingUtil {
         } 
         throw new NumberFormatException("Number " + num + ", instanceOf " + num.getClass().getName());
     }    
-    
+
     public static void main(String[] args) {
-        FormattingUtil fu = new FormattingUtil(7, 15);
+        FormattingUtil fu = new FormattingUtil(7, 15, true);
         System.out.println("=== DOUBLE ===");
         System.out.println(fu.formatNumber(123e-3));
         System.out.println(fu.formatNumber(-123e-3));
         System.out.println(fu.formatNumber(Double.POSITIVE_INFINITY));
         System.out.println(fu.formatNumber(Double.NEGATIVE_INFINITY));
         System.out.println(fu.formatNumber(Double.NaN));
-        System.out.println(fu.formatNumber(0));
+        System.out.println(fu.formatNumber(0.0));
         System.out.println(fu.formatNumber(0.25));
         System.out.println(fu.formatNumber(0.1));
-        System.out.println(fu.formatNumber(1));
+        System.out.println(fu.formatNumber(1.0));
         System.out.println(fu.formatNumber(-0.25));
         System.out.println(fu.formatNumber(-0.1));
-        System.out.println(fu.formatNumber(-1));
+        System.out.println(fu.formatNumber(-1.0));
         System.out.println(fu.formatNumber(0.9999));
         System.out.println(fu.formatNumber(0.0999999999999999999));
         System.out.println(fu.formatNumber(0.0099999999999999999999));
@@ -281,6 +322,8 @@ public class FormattingUtil {
         System.out.println(fu.formatNumber(999999.999));
         System.out.println(fu.formatNumber(999999.99));
         System.out.println(fu.formatNumber(999999.9));
+        System.out.println(fu.formatNumber(999999.0));
+        // Note that this will invoke formatNumber(float), not formatNumber(double)!
         System.out.println(fu.formatNumber(999999));
 
         System.out.println("=== FLOAT ===");
@@ -326,17 +369,6 @@ public class FormattingUtil {
         System.out.println(fu.formatNumber(1000000000.000000f));
         System.out.println(fu.formatNumber(100000000000.0000f));
         System.out.println(fu.formatNumber(10000000000000.00f));
-        System.out.println(fu.formatNumber(999999.99999999999999f));
-        System.out.println(fu.formatNumber(999999.9999999999999f));
-        System.out.println(fu.formatNumber(999999.999999999999f));
-        System.out.println(fu.formatNumber(999999.99999999999f));
-        System.out.println(fu.formatNumber(999999.9999999999f));
-        System.out.println(fu.formatNumber(999999.999999999f));
-        System.out.println(fu.formatNumber(999999.99999999f));
-        System.out.println(fu.formatNumber(999999.9999999f));
-        System.out.println(fu.formatNumber(999999.999999f));
-        System.out.println(fu.formatNumber(999999.99999f));
-        System.out.println(fu.formatNumber(999999.9999f));
         System.out.println(fu.formatNumber(999999.999f));
         System.out.println(fu.formatNumber(999999.99f));
         System.out.println(fu.formatNumber(999999.9f));