1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.lang;
18 
19 import java.math.BigDecimal;
20 import java.math.BigInteger;
21 
22 /**
23  * <p>Provides extra functionality for Java Number classes.</p>
24  *
25  * @author Apache Software Foundation
26  * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
27  * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
28  * @author Eric Pugh
29  * @author Phil Steitz
30  * @since 1.0
31  * @version $Id: NumberUtils.java 905636 2010-02-02 14:03:32Z niallp $
32  *
33  * @deprecated Moved to org.apache.commons.lang.math.
34  *             Class will be removed in Commons Lang 3.0.
35  */
36 public final class NumberUtils {
37     // DEPRECATED CLASS !!!
38 
39     /**
40      * <p><code>NumberUtils</code> instances should NOT be constructed in standard programming.
41      * Instead, the class should be used as <code>NumberUtils.stringToInt("6");</code>.</p>
42      *
43      * <p>This constructor is public to permit tools that require a JavaBean instance
44      * to operate.</p>
45      */
NumberUtils()46     public NumberUtils() {
47       super();
48     }
49 
50     //--------------------------------------------------------------------
51 
52     /**
53      * <p>Convert a <code>String</code> to an <code>int</code>, returning
54      * <code>zero</code> if the conversion fails.</p>
55      *
56      * @param str  the string to convert
57      * @return the int represented by the string, or <code>zero</code> if
58      *  conversion fails
59      */
stringToInt(String str)60     public static int stringToInt(String str) {
61         return stringToInt(str, 0);
62     }
63 
64     /**
65      * <p>Convert a <code>String</code> to an <code>int</code>, returning a
66      * default value if the conversion fails.</p>
67      *
68      * @param str  the string to convert
69      * @param defaultValue  the default value
70      * @return the int represented by the string, or the default if conversion fails
71      */
stringToInt(String str, int defaultValue)72     public static int stringToInt(String str, int defaultValue) {
73         try {
74             return Integer.parseInt(str);
75         } catch (NumberFormatException nfe) {
76             return defaultValue;
77         }
78     }
79 
80     //--------------------------------------------------------------------
81 
82     // must handle Long, Float, Integer, Float, Short,
83     //                  BigDecimal, BigInteger and Byte
84     // useful methods:
85     // Byte.decode(String)
86     // Byte.valueOf(String,int radix)
87     // Byte.valueOf(String)
88     // Double.valueOf(String)
89     // Float.valueOf(String)
90     // new Float(String)
91     // Integer.valueOf(String,int radix)
92     // Integer.valueOf(String)
93     // Integer.decode(String)
94     // Integer.getInteger(String)
95     // Integer.getInteger(String,int val)
96     // Integer.getInteger(String,Integer val)
97     // new Integer(String)
98     // new Double(String)
99     // new Byte(String)
100     // new Long(String)
101     // Long.getLong(String)
102     // Long.getLong(String,int)
103     // Long.getLong(String,Integer)
104     // Long.valueOf(String,int)
105     // Long.valueOf(String)
106     // new Short(String)
107     // Short.decode(String)
108     // Short.valueOf(String,int)
109     // Short.valueOf(String)
110     // new BigDecimal(String)
111     // new BigInteger(String)
112     // new BigInteger(String,int radix)
113     // Possible inputs:
114     // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
115     // plus minus everything. Prolly more. A lot are not separable.
116 
117     /**
118      * <p>Turns a string value into a java.lang.Number.</p>
119      *
120      * <p>First, the value is examined for a type qualifier on the end
121      * (<code>'f','F','d','D','l','L'</code>).  If it is found, it starts
122      * trying to create successively larger types from the type specified
123      * until one is found that can hold the value.</p>
124      *
125      * <p>If a type specifier is not found, it will check for a decimal point
126      * and then try successively larger types from <code>Integer</code> to
127      * <code>BigInteger</code> and from <code>Float</code> to
128      * <code>BigDecimal</code>.</p>
129      *
130      * <p>If the string starts with <code>0x</code> or <code>-0x</code>, it
131      * will be interpreted as a hexadecimal integer.  Values with leading
132      * <code>0</code>'s will not be interpreted as octal.</p>
133      *
134      * @param val String containing a number
135      * @return Number created from the string
136      * @throws NumberFormatException if the value cannot be converted
137      */
createNumber(String val)138     public static Number createNumber(String val) throws NumberFormatException {
139         if (val == null) {
140             return null;
141         }
142         if (val.length() == 0) {
143             throw new NumberFormatException("\"\" is not a valid number.");
144         }
145         if (val.length() == 1 && !Character.isDigit(val.charAt(0))) {
146             throw new NumberFormatException(val + " is not a valid number.");
147         }
148         if (val.startsWith("--")) {
149             // this is protection for poorness in java.lang.BigDecimal.
150             // it accepts this as a legal value, but it does not appear
151             // to be in specification of class. OS X Java parses it to
152             // a wrong value.
153             return null;
154         }
155         if (val.startsWith("0x") || val.startsWith("-0x")) {
156             return createInteger(val);
157         }
158         char lastChar = val.charAt(val.length() - 1);
159         String mant;
160         String dec;
161         String exp;
162         int decPos = val.indexOf('.');
163         int expPos = val.indexOf('e') + val.indexOf('E') + 1;
164 
165         if (decPos > -1) {
166 
167             if (expPos > -1) {
168                 if (expPos < decPos) {
169                     throw new NumberFormatException(val + " is not a valid number.");
170                 }
171                 dec = val.substring(decPos + 1, expPos);
172             } else {
173                 dec = val.substring(decPos + 1);
174             }
175             mant = val.substring(0, decPos);
176         } else {
177             if (expPos > -1) {
178                 mant = val.substring(0, expPos);
179             } else {
180                 mant = val;
181             }
182             dec = null;
183         }
184         if (!Character.isDigit(lastChar)) {
185             if (expPos > -1 && expPos < val.length() - 1) {
186                 exp = val.substring(expPos + 1, val.length() - 1);
187             } else {
188                 exp = null;
189             }
190             //Requesting a specific type..
191             String numeric = val.substring(0, val.length() - 1);
192             boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
193             switch (lastChar) {
194                 case 'l' :
195                 case 'L' :
196                     if (dec == null
197                         && exp == null
198                         && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) {
199                         try {
200                             return createLong(numeric);
201                         } catch (NumberFormatException nfe) {
202                             //Too big for a long
203                         }
204                         return createBigInteger(numeric);
205 
206                     }
207                     throw new NumberFormatException(val + " is not a valid number.");
208                 case 'f' :
209                 case 'F' :
210                     try {
211                         Float f = NumberUtils.createFloat(numeric);
212                         if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
213                             //If it's too big for a float or the float value = 0 and the string
214                             //has non-zeros in it, then float does not have the precision we want
215                             return f;
216                         }
217 
218                     } catch (NumberFormatException e) {
219                         // ignore the bad number
220                     }
221                     //$FALL-THROUGH$
222                 case 'd' :
223                 case 'D' :
224                     try {
225                         Double d = NumberUtils.createDouble(numeric);
226                         if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
227                             return d;
228                         }
229                     } catch (NumberFormatException nfe) {
230                         // empty catch
231                     }
232                     try {
233                         return createBigDecimal(numeric);
234                     } catch (NumberFormatException e) {
235                         // empty catch
236                     }
237                     //$FALL-THROUGH$
238                 default :
239                     throw new NumberFormatException(val + " is not a valid number.");
240 
241             }
242         } else {
243             //User doesn't have a preference on the return type, so let's start
244             //small and go from there...
245             if (expPos > -1 && expPos < val.length() - 1) {
246                 exp = val.substring(expPos + 1, val.length());
247             } else {
248                 exp = null;
249             }
250             if (dec == null && exp == null) {
251                 //Must be an int,long,bigint
252                 try {
253                     return createInteger(val);
254                 } catch (NumberFormatException nfe) {
255                     // empty catch
256                 }
257                 try {
258                     return createLong(val);
259                 } catch (NumberFormatException nfe) {
260                     // empty catch
261                 }
262                 return createBigInteger(val);
263 
264             } else {
265                 //Must be a float,double,BigDec
266                 boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
267                 try {
268                     Float f = createFloat(val);
269                     if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
270                         return f;
271                     }
272                 } catch (NumberFormatException nfe) {
273                     // empty catch
274                 }
275                 try {
276                     Double d = createDouble(val);
277                     if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
278                         return d;
279                     }
280                 } catch (NumberFormatException nfe) {
281                     // empty catch
282                 }
283 
284                 return createBigDecimal(val);
285 
286             }
287 
288         }
289     }
290 
291     /**
292      * <p>Utility method for {@link #createNumber(java.lang.String)}.</p>
293      *
294      * <p>Returns <code>true</code> if s is <code>null</code>.</p>
295      *
296      * @param s the String to check
297      * @return if it is all zeros or <code>null</code>
298      */
isAllZeros(String s)299     private static boolean isAllZeros(String s) {
300         if (s == null) {
301             return true;
302         }
303         for (int i = s.length() - 1; i >= 0; i--) {
304             if (s.charAt(i) != '0') {
305                 return false;
306             }
307         }
308         return s.length() > 0;
309     }
310 
311     //--------------------------------------------------------------------
312 
313     /**
314      * <p>Convert a <code>String</code> to a <code>Float</code>.</p>
315      *
316      * @param val  a <code>String</code> to convert
317      * @return converted <code>Float</code>
318      * @throws NumberFormatException if the value cannot be converted
319      */
createFloat(String val)320     public static Float createFloat(String val) {
321         return Float.valueOf(val);
322     }
323 
324     /**
325      * <p>Convert a <code>String</code> to a <code>Double</code>.</p>
326      *
327      * @param val  a <code>String</code> to convert
328      * @return converted <code>Double</code>
329      * @throws NumberFormatException if the value cannot be converted
330      */
createDouble(String val)331     public static Double createDouble(String val) {
332         return Double.valueOf(val);
333     }
334 
335     /**
336      * <p>Convert a <code>String</code> to a <code>Integer</code>, handling
337      * hex and octal notations.</p>
338      *
339      * @param val  a <code>String</code> to convert
340      * @return converted <code>Integer</code>
341      * @throws NumberFormatException if the value cannot be converted
342      */
createInteger(String val)343     public static Integer createInteger(String val) {
344         // decode() handles 0xAABD and 0777 (hex and octal) as well.
345         return Integer.decode(val);
346     }
347 
348     /**
349      * <p>Convert a <code>String</code> to a <code>Long</code>.</p>
350      *
351      * @param val  a <code>String</code> to convert
352      * @return converted <code>Long</code>
353      * @throws NumberFormatException if the value cannot be converted
354      */
createLong(String val)355     public static Long createLong(String val) {
356         return Long.valueOf(val);
357     }
358 
359     /**
360      * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p>
361      *
362      * @param val  a <code>String</code> to convert
363      * @return converted <code>BigInteger</code>
364      * @throws NumberFormatException if the value cannot be converted
365      */
createBigInteger(String val)366     public static BigInteger createBigInteger(String val) {
367         BigInteger bi = new BigInteger(val);
368         return bi;
369     }
370 
371     /**
372      * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p>
373      *
374      * @param val  a <code>String</code> to convert
375      * @return converted <code>BigDecimal</code>
376      * @throws NumberFormatException if the value cannot be converted
377      */
createBigDecimal(String val)378     public static BigDecimal createBigDecimal(String val) {
379         BigDecimal bd = new BigDecimal(val);
380         return bd;
381     }
382 
383     //--------------------------------------------------------------------
384 
385     /**
386      * <p>Gets the minimum of three <code>long</code> values.</p>
387      *
388      * @param a  value 1
389      * @param b  value 2
390      * @param c  value 3
391      * @return  the smallest of the values
392      */
minimum(long a, long b, long c)393     public static long minimum(long a, long b, long c) {
394         if (b < a) {
395             a = b;
396         }
397         if (c < a) {
398             a = c;
399         }
400         return a;
401     }
402 
403     /**
404      * <p>Gets the minimum of three <code>int</code> values.</p>
405      *
406      * @param a  value 1
407      * @param b  value 2
408      * @param c  value 3
409      * @return  the smallest of the values
410      */
minimum(int a, int b, int c)411     public static int minimum(int a, int b, int c) {
412         if (b < a) {
413             a = b;
414         }
415         if (c < a) {
416             a = c;
417         }
418         return a;
419     }
420 
421     /**
422      * <p>Gets the maximum of three <code>long</code> values.</p>
423      *
424      * @param a  value 1
425      * @param b  value 2
426      * @param c  value 3
427      * @return  the largest of the values
428      */
maximum(long a, long b, long c)429     public static long maximum(long a, long b, long c) {
430         if (b > a) {
431             a = b;
432         }
433         if (c > a) {
434             a = c;
435         }
436         return a;
437     }
438 
439     /**
440      * <p>Gets the maximum of three <code>int</code> values.</p>
441      *
442      * @param a  value 1
443      * @param b  value 2
444      * @param c  value 3
445      * @return  the largest of the values
446      */
maximum(int a, int b, int c)447     public static int maximum(int a, int b, int c) {
448         if (b > a) {
449             a = b;
450         }
451         if (c > a) {
452             a = c;
453         }
454         return a;
455     }
456 
457     //--------------------------------------------------------------------
458 
459     /**
460      * <p>Compares two <code>doubles</code> for order.</p>
461      *
462      * <p>This method is more comprehensive than the standard Java greater
463      * than, less than and equals operators.</p>
464      * <ul>
465      *  <li>It returns <code>-1</code> if the first value is less than the second.
466      *  <li>It returns <code>+1</code> if the first value is greater than the second.
467      *  <li>It returns <code>0</code> if the values are equal.
468      * </ul>
469      *
470      * <p>
471      * The ordering is as follows, largest to smallest:
472      * <ul>
473      *  <li>NaN
474      *  <li>Positive infinity
475      *  <li>Maximum double
476      *  <li>Normal positive numbers
477      *  <li>+0.0
478      *  <li>-0.0
479      *  <li>Normal negative numbers
480      *  <li>Minimum double (-Double.MAX_VALUE)
481      *  <li>Negative infinity
482      * </ul>
483      * </p>
484      *
485      * <p>Comparing <code>NaN</code> with <code>NaN</code> will
486      * return <code>0</code>.</p>
487      *
488      * @param lhs  the first <code>double</code>
489      * @param rhs  the second <code>double</code>
490      * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
491      *  <code>0</code> if equal to rhs
492      */
compare(double lhs, double rhs)493     public static int compare(double lhs, double rhs) {
494         if (lhs < rhs) {
495             return -1;
496         }
497         if (lhs > rhs) {
498             return +1;
499         }
500         // Need to compare bits to handle 0.0 == -0.0 being true
501         // compare should put -0.0 < +0.0
502         // Two NaNs are also == for compare purposes
503         // where NaN == NaN is false
504         long lhsBits = Double.doubleToLongBits(lhs);
505         long rhsBits = Double.doubleToLongBits(rhs);
506         if (lhsBits == rhsBits) {
507             return 0;
508         }
509         // Something exotic! A comparison to NaN or 0.0 vs -0.0
510         // Fortunately NaN's long is > than everything else
511         // Also negzeros bits < poszero
512         // NAN: 9221120237041090560
513         // MAX: 9218868437227405311
514         // NEGZERO: -9223372036854775808
515         if (lhsBits < rhsBits) {
516             return -1;
517         } else {
518             return +1;
519         }
520     }
521 
522     /**
523      * <p>Compares two floats for order.</p>
524      *
525      * <p>This method is more comprehensive than the standard Java greater than,
526      * less than and equals operators.</p>
527      * <ul>
528      *  <li>It returns <code>-1</code> if the first value is less than the second.
529      *  <li>It returns <code>+1</code> if the first value is greater than the second.
530      *  <li>It returns <code>0</code> if the values are equal.
531      * </ul>
532      *
533      * <p> The ordering is as follows, largest to smallest:
534      * <ul>
535      * <li>NaN
536      * <li>Positive infinity
537      * <li>Maximum float
538      * <li>Normal positive numbers
539      * <li>+0.0
540      * <li>-0.0
541      * <li>Normal negative numbers
542      * <li>Minimum float (-Float.MAX_VALUE)
543      * <li>Negative infinity
544      * </ul>
545      *
546      * <p>Comparing <code>NaN</code> with <code>NaN</code> will return
547      * <code>0</code>.</p>
548      *
549      * @param lhs  the first <code>float</code>
550      * @param rhs  the second <code>float</code>
551      * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
552      *  <code>0</code> if equal to rhs
553      */
compare(float lhs, float rhs)554     public static int compare(float lhs, float rhs) {
555         if (lhs < rhs) {
556             return -1;
557         }
558         if (lhs > rhs) {
559             return +1;
560         }
561         //Need to compare bits to handle 0.0 == -0.0 being true
562         // compare should put -0.0 < +0.0
563         // Two NaNs are also == for compare purposes
564         // where NaN == NaN is false
565         int lhsBits = Float.floatToIntBits(lhs);
566         int rhsBits = Float.floatToIntBits(rhs);
567         if (lhsBits == rhsBits) {
568             return 0;
569         }
570         //Something exotic! A comparison to NaN or 0.0 vs -0.0
571         //Fortunately NaN's int is > than everything else
572         //Also negzeros bits < poszero
573         //NAN: 2143289344
574         //MAX: 2139095039
575         //NEGZERO: -2147483648
576         if (lhsBits < rhsBits) {
577             return -1;
578         } else {
579             return +1;
580         }
581     }
582 
583     //--------------------------------------------------------------------
584 
585     /**
586      * <p>Checks whether the <code>String</code> contains only
587      * digit characters.</p>
588      *
589      * <p><code>Null</code> and empty String will return
590      * <code>false</code>.</p>
591      *
592      * @param str  the <code>String</code> to check
593      * @return <code>true</code> if str contains only unicode numeric
594      */
isDigits(String str)595     public static boolean isDigits(String str) {
596         if ((str == null) || (str.length() == 0)) {
597             return false;
598         }
599         for (int i = 0; i < str.length(); i++) {
600             if (!Character.isDigit(str.charAt(i))) {
601                 return false;
602             }
603         }
604         return true;
605     }
606 
607     /**
608      * <p>Checks whether the String a valid Java number.</p>
609      *
610      * <p>Valid numbers include hexadecimal marked with the <code>0x</code>
611      * qualifier, scientific notation and numbers marked with a type
612      * qualifier (e.g. 123L).</p>
613      *
614      * <p><code>Null</code> and empty String will return
615      * <code>false</code>.</p>
616      *
617      * @param str  the <code>String</code> to check
618      * @return <code>true</code> if the string is a correctly formatted number
619      */
isNumber(String str)620     public static boolean isNumber(String str) {
621         if (StringUtils.isEmpty(str)) {
622             return false;
623         }
624         char[] chars = str.toCharArray();
625         int sz = chars.length;
626         boolean hasExp = false;
627         boolean hasDecPoint = false;
628         boolean allowSigns = false;
629         boolean foundDigit = false;
630         // deal with any possible sign up front
631         int start = (chars[0] == '-') ? 1 : 0;
632         if (sz > start + 1) {
633             if (chars[start] == '0' && chars[start + 1] == 'x') {
634                 int i = start + 2;
635                 if (i == sz) {
636                     return false; // str == "0x"
637                 }
638                 // checking hex (it can't be anything else)
639                 for (; i < chars.length; i++) {
640                     if ((chars[i] < '0' || chars[i] > '9')
641                         && (chars[i] < 'a' || chars[i] > 'f')
642                         && (chars[i] < 'A' || chars[i] > 'F')) {
643                         return false;
644                     }
645                 }
646                 return true;
647             }
648         }
649         sz--; // don't want to loop to the last char, check it afterwords
650               // for type qualifiers
651         int i = start;
652         // loop to the next to last char or to the last char if we need another digit to
653         // make a valid number (e.g. chars[0..5] = "1234E")
654         while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
655             if (chars[i] >= '0' && chars[i] <= '9') {
656                 foundDigit = true;
657                 allowSigns = false;
658 
659             } else if (chars[i] == '.') {
660                 if (hasDecPoint || hasExp) {
661                     // two decimal points or dec in exponent
662                     return false;
663                 }
664                 hasDecPoint = true;
665             } else if (chars[i] == 'e' || chars[i] == 'E') {
666                 // we've already taken care of hex.
667                 if (hasExp) {
668                     // two E's
669                     return false;
670                 }
671                 if (!foundDigit) {
672                     return false;
673                 }
674                 hasExp = true;
675                 allowSigns = true;
676             } else if (chars[i] == '+' || chars[i] == '-') {
677                 if (!allowSigns) {
678                     return false;
679                 }
680                 allowSigns = false;
681                 foundDigit = false; // we need a digit after the E
682             } else {
683                 return false;
684             }
685             i++;
686         }
687         if (i < chars.length) {
688             if (chars[i] >= '0' && chars[i] <= '9') {
689                 // no type qualifier, OK
690                 return true;
691             }
692             if (chars[i] == 'e' || chars[i] == 'E') {
693                 // can't have an E at the last byte
694                 return false;
695             }
696             if (!allowSigns
697                 && (chars[i] == 'd'
698                     || chars[i] == 'D'
699                     || chars[i] == 'f'
700                     || chars[i] == 'F')) {
701                 return foundDigit;
702             }
703             if (chars[i] == 'l'
704                 || chars[i] == 'L') {
705                 // not allowing L with an exponent
706                 return foundDigit && !hasExp;
707             }
708             // last character is illegal
709             return false;
710         }
711         // allowSigns is true iff the val ends in 'E'
712         // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
713         return !allowSigns && foundDigit;
714     }
715 }
716