b5c8717e6b0fdcd6f53176ff978bbc262dcc13b7
[jalview.git] / srcjar / javajs / util / DF.java
1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2007-04-26 16:57:51 -0500 (Thu, 26 Apr 2007) $
4  * $Revision: 7502 $
5  *
6  * Some portions of this file have been modified by Robert Hanson hansonr.at.stolaf.edu 2012-2017
7  * for use in SwingJS via transpilation into JavaScript using Java2Script.
8  *
9  * Copyright (C) 2005  The Jmol Development Team
10  *
11  * Contact: jmol-developers@lists.sf.net
12  *
13  *  This library is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU Lesser General Public
15  *  License as published by the Free Software Foundation; either
16  *  version 2.1 of the License, or (at your option) any later version.
17  *
18  *  This library is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  *  Lesser General Public License for more details.
22  *
23  *  You should have received a copy of the GNU Lesser General Public
24  *  License along with this library; if not, write to the Free Software
25  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 package javajs.util;
29
30 /**
31  * created to remove ambiguities and make a simpler DecimalFormat
32  */
33 public class DF {
34
35   private final static String[] formattingStrings = { "0", "0.0", "0.00",
36       "0.000", "0.0000", "0.00000", "0.000000", "0.0000000", "0.00000000",
37       "0.000000000" };
38   private final static String zeros = "0000000000000000000000000000000000000000";
39
40   private final static float[] formatAdds = { 0.5f, 0.05f, 0.005f, 0.0005f,
41       0.00005f, 0.000005f, 0.0000005f, 0.00000005f, 0.000000005f, 0.0000000005f };
42
43   private final static Boolean[] useNumberLocalization = new Boolean[] { Boolean.TRUE };
44
45   public static void setUseNumberLocalization(boolean TF) {
46     useNumberLocalization[0] = (TF ? Boolean.TRUE : Boolean.FALSE);
47   }
48
49   public static String formatDecimalDbl(double value, int decimalDigits) {
50     if (decimalDigits == Integer.MAX_VALUE 
51         || value == Double.NEGATIVE_INFINITY
52         || value == Double.POSITIVE_INFINITY 
53         || Double.isNaN(value))
54       return "" + value;
55     return DF.formatDecimal((float) value, decimalDigits);
56   }
57
58   /**
59    * a simple alternative to DecimalFormat (which Java2Script does not have
60    * and which is quite too complex for our use here.)
61    * 
62    * @param value
63    * @param decimalDigits
64    * @return  formatted decimal
65    */
66   public static String formatDecimal(float value, int decimalDigits) {
67     if (decimalDigits == Integer.MAX_VALUE 
68         || value == Float.NEGATIVE_INFINITY || value == Float.POSITIVE_INFINITY || Float.isNaN(value))
69       return "" + value;
70     int n;
71     if (decimalDigits < 0) {
72       decimalDigits = -decimalDigits;
73       if (decimalDigits > formattingStrings.length)
74         decimalDigits = formattingStrings.length;
75       if (value == 0)
76         return formattingStrings[decimalDigits - 1] + "E+0";
77       //scientific notation
78       n = 0;
79       double d;
80       if (Math.abs(value) < 1) {
81         n = 10;
82         d = value * 1e-10;
83       } else {
84         n = -10;
85         d = value * 1e10;
86       }
87       String s = ("" + d).toUpperCase();
88       int i = s.indexOf("E");
89       n = PT.parseInt(s.substring(i + 1)) + n;
90       String sf;
91       if (i < 0) {
92         sf = "" + value;
93       } else {
94         float f = PT.parseFloat(s.substring(0, i));
95         if (f == 10 || f == -10) {
96           //d = 9.99999997465; n = -6 --> 10.00000E-5
97           f /= 10;
98           n += (n < 0 ? 1 : -1);          
99         }
100         sf = formatDecimal(f, decimalDigits - 1);
101       }
102       return sf  + "E" + (n >= 0 ? "+" : "") + n;
103     }
104   
105     if (decimalDigits >= formattingStrings.length)
106       decimalDigits = formattingStrings.length - 1;
107     String s1 = ("" + value).toUpperCase();
108     int pt = s1.indexOf(".");
109     if (pt < 0) // specifically JavaScript "-2" not "-2.0"
110       return s1 + formattingStrings[decimalDigits].substring(1);
111     boolean isNeg = s1.startsWith("-");
112     if (isNeg) {
113       s1 = s1.substring(1);
114       pt--;
115     }
116     int pt1 = s1.indexOf("E-");
117     if (pt1 > 0) {
118       n = PT.parseInt(s1.substring(pt1 + 1));
119       // 3.567E-2
120       // 0.03567
121       s1 = "0." + zeros.substring(0, -n - 1) + s1.substring(0, 1) + s1.substring(2, pt1);
122       pt = 1; 
123     }
124   
125     pt1 = s1.indexOf("E");
126     // 3.5678E+3
127     // 3567.800000000
128     // 1.234E10 %3.8f -> 12340000000.00000000
129     if (pt1 > 0) {
130       n = PT.parseInt(s1.substring(pt1 + 1));
131       s1 = s1.substring(0, 1) + s1.substring(2, pt1) + zeros;
132       s1 = s1.substring(0, n + 1) + "." + s1.substring(n + 1);
133       pt = s1.indexOf(".");
134     } 
135     // "234.345667  len == 10; pt = 3
136     // "  0.0 "  decimalDigits = 1
137     
138     int len = s1.length();
139     int pt2 = decimalDigits + pt + 1;
140     if (pt2 < len && s1.charAt(pt2) >= '5') {
141       return formatDecimal(
142           value + (isNeg ? -1 : 1) * formatAdds[decimalDigits], decimalDigits);
143     }
144   
145     SB sb = SB.newS(s1.substring(0, (decimalDigits == 0 ? pt
146         : ++pt)));
147     for (int i = 0; i < decimalDigits; i++, pt++) {
148       if (pt < len)
149         sb.appendC(s1.charAt(pt));
150       else
151         sb.appendC('0');
152     }
153     s1 = (isNeg ? "-" : "") + sb;
154     return (Boolean.TRUE.equals(useNumberLocalization[0]) ? s1 : s1.replace(',',
155         '.'));
156   }
157
158   /**
159    * an alternative to DecimalFormat "0.#"
160    * 
161    * @param x
162    * @param precision
163    * @return  formatted number 
164    */
165   public static String formatDecimalTrimmed(double x, int precision) {
166     String str = formatDecimalDbl(x, precision);
167     int m = str.length() - 1;
168     char zero = '0';
169     while (m >= 0 && str.charAt(m) == zero)
170       m--;
171     return str.substring(0, m + 1); // 0.##...
172   }
173
174 }