001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.lang;
018    
019    import java.math.BigDecimal;
020    import java.math.BigInteger;
021    
022    /**
023     * <p>Provides extra functionality for Java Number classes.</p>
024     *
025     * @author Apache Software Foundation
026     * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
027     * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
028     * @author Eric Pugh
029     * @author Phil Steitz
030     * @since 1.0
031     * @version $Id: NumberUtils.java 905636 2010-02-02 14:03:32Z niallp $
032     * 
033     * @deprecated Moved to org.apache.commons.lang.math.
034     *             Class will be removed in Commons Lang 3.0.
035     */
036    public final class NumberUtils {
037        // DEPRECATED CLASS !!!
038        
039        /**
040         * <p><code>NumberUtils</code> instances should NOT be constructed in standard programming.
041         * Instead, the class should be used as <code>NumberUtils.stringToInt("6");</code>.</p>
042         *
043         * <p>This constructor is public to permit tools that require a JavaBean instance
044         * to operate.</p>
045         */
046        public NumberUtils() {
047          super();
048        }
049    
050        //--------------------------------------------------------------------
051        
052        /**
053         * <p>Convert a <code>String</code> to an <code>int</code>, returning
054         * <code>zero</code> if the conversion fails.</p>
055         * 
056         * @param str  the string to convert
057         * @return the int represented by the string, or <code>zero</code> if
058         *  conversion fails
059         */
060        public static int stringToInt(String str) {
061            return stringToInt(str, 0);
062        }
063    
064        /**
065         * <p>Convert a <code>String</code> to an <code>int</code>, returning a
066         * default value if the conversion fails.</p>
067         * 
068         * @param str  the string to convert
069         * @param defaultValue  the default value
070         * @return the int represented by the string, or the default if conversion fails
071         */
072        public static int stringToInt(String str, int defaultValue) {
073            try {
074                return Integer.parseInt(str);
075            } catch (NumberFormatException nfe) {
076                return defaultValue;
077            }
078        }
079    
080        //--------------------------------------------------------------------
081        
082        // must handle Long, Float, Integer, Float, Short,
083        //                  BigDecimal, BigInteger and Byte
084        // useful methods:
085        // Byte.decode(String)
086        // Byte.valueOf(String,int radix)
087        // Byte.valueOf(String)
088        // Double.valueOf(String)
089        // Float.valueOf(String)
090        // new Float(String)
091        // Integer.valueOf(String,int radix)
092        // Integer.valueOf(String)
093        // Integer.decode(String)
094        // Integer.getInteger(String)
095        // Integer.getInteger(String,int val)
096        // Integer.getInteger(String,Integer val)
097        // new Integer(String)
098        // new Double(String)
099        // 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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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    }