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 <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
026     * @author Stephen Colebourne
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 488819 2006-12-19 21:50:04Z bayard $
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.startsWith("--")) {
146                // this is protection for poorness in java.lang.BigDecimal.
147                // it accepts this as a legal value, but it does not appear 
148                // to be in specification of class. OS X Java parses it to 
149                // a wrong value.
150                return null;
151            }
152            if (val.startsWith("0x") || val.startsWith("-0x")) {
153                return createInteger(val);
154            }   
155            char lastChar = val.charAt(val.length() - 1);
156            String mant;
157            String dec;
158            String exp;
159            int decPos = val.indexOf('.');
160            int expPos = val.indexOf('e') + val.indexOf('E') + 1;
161    
162            if (decPos > -1) {
163    
164                if (expPos > -1) {
165                    if (expPos < decPos) {
166                        throw new NumberFormatException(val + " is not a valid number.");
167                    }
168                    dec = val.substring(decPos + 1, expPos);
169                } else {
170                    dec = val.substring(decPos + 1);
171                }
172                mant = val.substring(0, decPos);
173            } else {
174                if (expPos > -1) {
175                    mant = val.substring(0, expPos);
176                } else {
177                    mant = val;
178                }
179                dec = null;
180            }
181            if (!Character.isDigit(lastChar)) {
182                if (expPos > -1 && expPos < val.length() - 1) {
183                    exp = val.substring(expPos + 1, val.length() - 1);
184                } else {
185                    exp = null;
186                }
187                //Requesting a specific type..
188                String numeric = val.substring(0, val.length() - 1);
189                boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
190                switch (lastChar) {
191                    case 'l' :
192                    case 'L' :
193                        if (dec == null
194                            && exp == null
195                            && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) {
196                            try {
197                                return createLong(numeric);
198                            } catch (NumberFormatException nfe) {
199                                //Too big for a long
200                            }
201                            return createBigInteger(numeric);
202    
203                        }
204                        throw new NumberFormatException(val + " is not a valid number.");
205                    case 'f' :
206                    case 'F' :
207                        try {
208                            Float f = NumberUtils.createFloat(numeric);
209                            if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
210                                //If it's too big for a float or the float value = 0 and the string
211                                //has non-zeros in it, then float does not have the precision we want
212                                return f;
213                            }
214    
215                        } catch (NumberFormatException e) {
216                            // ignore the bad number
217                        }
218                        //Fall through
219                    case 'd' :
220                    case 'D' :
221                        try {
222                            Double d = NumberUtils.createDouble(numeric);
223                            if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
224                                return d;
225                            }
226                        } catch (NumberFormatException nfe) {
227                            // empty catch
228                        }
229                        try {
230                            return createBigDecimal(numeric);
231                        } catch (NumberFormatException e) {
232                            // empty catch
233                        }
234                        //Fall through
235                    default :
236                        throw new NumberFormatException(val + " is not a valid number.");
237    
238                }
239            } else {
240                //User doesn't have a preference on the return type, so let's start
241                //small and go from there...
242                if (expPos > -1 && expPos < val.length() - 1) {
243                    exp = val.substring(expPos + 1, val.length());
244                } else {
245                    exp = null;
246                }
247                if (dec == null && exp == null) {
248                    //Must be an int,long,bigint
249                    try {
250                        return createInteger(val);
251                    } catch (NumberFormatException nfe) {
252                        // empty catch
253                    }
254                    try {
255                        return createLong(val);
256                    } catch (NumberFormatException nfe) {
257                        // empty catch
258                    }
259                    return createBigInteger(val);
260    
261                } else {
262                    //Must be a float,double,BigDec
263                    boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
264                    try {
265                        Float f = createFloat(val);
266                        if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
267                            return f;
268                        }
269                    } catch (NumberFormatException nfe) {
270                        // empty catch
271                    }
272                    try {
273                        Double d = createDouble(val);
274                        if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
275                            return d;
276                        }
277                    } catch (NumberFormatException nfe) {
278                        // empty catch
279                    }
280    
281                    return createBigDecimal(val);
282    
283                }
284    
285            }
286        }
287    
288        /**
289         * <p>Utility method for {@link #createNumber(java.lang.String)}.</p>
290         *
291         * <p>Returns <code>true</code> if s is <code>null</code>.</p>
292         * 
293         * @param s the String to check
294         * @return if it is all zeros or <code>null</code>
295         */
296        private static boolean isAllZeros(String s) {
297            if (s == null) {
298                return true;
299            }
300            for (int i = s.length() - 1; i >= 0; i--) {
301                if (s.charAt(i) != '0') {
302                    return false;
303                }
304            }
305            return s.length() > 0;
306        }
307    
308        //--------------------------------------------------------------------
309        
310        /**
311         * <p>Convert a <code>String</code> to a <code>Float</code>.</p>
312         * 
313         * @param val  a <code>String</code> to convert
314         * @return converted <code>Float</code>
315         * @throws NumberFormatException if the value cannot be converted
316         */
317        public static Float createFloat(String val) {
318            return Float.valueOf(val);
319        }
320    
321        /**
322         * <p>Convert a <code>String</code> to a <code>Double</code>.</p>
323         * 
324         * @param val  a <code>String</code> to convert
325         * @return converted <code>Double</code>
326         * @throws NumberFormatException if the value cannot be converted
327         */
328        public static Double createDouble(String val) {
329            return Double.valueOf(val);
330        }
331    
332        /**
333         * <p>Convert a <code>String</code> to a <code>Integer</code>, handling
334         * hex and octal notations.</p>
335         * 
336         * @param val  a <code>String</code> to convert
337         * @return converted <code>Integer</code>
338         * @throws NumberFormatException if the value cannot be converted
339         */
340        public static Integer createInteger(String val) {
341            // decode() handles 0xAABD and 0777 (hex and octal) as well.
342            return Integer.decode(val);
343        }
344    
345        /**
346         * <p>Convert a <code>String</code> to a <code>Long</code>.</p>
347         * 
348         * @param val  a <code>String</code> to convert
349         * @return converted <code>Long</code>
350         * @throws NumberFormatException if the value cannot be converted
351         */
352        public static Long createLong(String val) {
353            return Long.valueOf(val);
354        }
355    
356        /**
357         * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p>
358         * 
359         * @param val  a <code>String</code> to convert
360         * @return converted <code>BigInteger</code>
361         * @throws NumberFormatException if the value cannot be converted
362         */
363        public static BigInteger createBigInteger(String val) {
364            BigInteger bi = new BigInteger(val);
365            return bi;
366        }
367    
368        /**
369         * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p>
370         * 
371         * @param val  a <code>String</code> to convert
372         * @return converted <code>BigDecimal</code>
373         * @throws NumberFormatException if the value cannot be converted
374         */
375        public static BigDecimal createBigDecimal(String val) {
376            BigDecimal bd = new BigDecimal(val);
377            return bd;
378        }
379    
380        //--------------------------------------------------------------------
381        
382        /**
383         * <p>Gets the minimum of three <code>long</code> values.</p>
384         * 
385         * @param a  value 1
386         * @param b  value 2
387         * @param c  value 3
388         * @return  the smallest of the values
389         */
390        public static long minimum(long a, long b, long c) {
391            if (b < a) {
392                a = b;
393            }
394            if (c < a) {
395                a = c;
396            }
397            return a;
398        }
399    
400        /**
401         * <p>Gets the minimum of three <code>int</code> values.</p>
402         * 
403         * @param a  value 1
404         * @param b  value 2
405         * @param c  value 3
406         * @return  the smallest of the values
407         */
408        public static int minimum(int a, int b, int c) {
409            if (b < a) {
410                a = b;
411            }
412            if (c < a) {
413                a = c;
414            }
415            return a;
416        }
417    
418        /**
419         * <p>Gets the maximum of three <code>long</code> values.</p>
420         * 
421         * @param a  value 1
422         * @param b  value 2
423         * @param c  value 3
424         * @return  the largest of the values
425         */
426        public static long maximum(long a, long b, long c) {
427            if (b > a) {
428                a = b;
429            }
430            if (c > a) {
431                a = c;
432            }
433            return a;
434        }
435    
436        /**
437         * <p>Gets the maximum of three <code>int</code> values.</p>
438         * 
439         * @param a  value 1
440         * @param b  value 2
441         * @param c  value 3
442         * @return  the largest of the values
443         */
444        public static int maximum(int a, int b, int c) {
445            if (b > a) {
446                a = b;
447            }
448            if (c > a) {
449                a = c;
450            }
451            return a;
452        }
453    
454        //--------------------------------------------------------------------
455        
456        /**
457         * <p>Compares two <code>doubles</code> for order.</p>
458         *
459         * <p>This method is more comprehensive than the standard Java greater
460         * than, less than and equals operators.</p>
461         * <ul>
462         *  <li>It returns <code>-1</code> if the first value is less than the second.
463         *  <li>It returns <code>+1</code> if the first value is greater than the second.
464         *  <li>It returns <code>0</code> if the values are equal.
465         * </ul>
466         *
467         * <p>
468         * The ordering is as follows, largest to smallest:
469         * <ul>
470         *  <li>NaN
471         *  <li>Positive infinity
472         *  <li>Maximum double
473         *  <li>Normal positive numbers
474         *  <li>+0.0
475         *  <li>-0.0
476         *  <li>Normal negative numbers
477         *  <li>Minimum double (-Double.MAX_VALUE)
478         *  <li>Negative infinity
479         * </ul>
480         * </p>
481         *
482         * <p>Comparing <code>NaN</code> with <code>NaN</code> will
483         * return <code>0</code>.</p>
484         * 
485         * @param lhs  the first <code>double</code>
486         * @param rhs  the second <code>double</code>
487         * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
488         *  <code>0</code> if equal to rhs
489         */
490        public static int compare(double lhs, double rhs) {
491            if (lhs < rhs) {
492                return -1;
493            }
494            if (lhs > rhs) {
495                return +1;
496            }
497            // Need to compare bits to handle 0.0 == -0.0 being true
498            // compare should put -0.0 < +0.0
499            // Two NaNs are also == for compare purposes
500            // where NaN == NaN is false
501            long lhsBits = Double.doubleToLongBits(lhs);
502            long rhsBits = Double.doubleToLongBits(rhs);
503            if (lhsBits == rhsBits) {
504                return 0;
505            }
506            // Something exotic! A comparison to NaN or 0.0 vs -0.0
507            // Fortunately NaN's long is > than everything else
508            // Also negzeros bits < poszero
509            // NAN: 9221120237041090560
510            // MAX: 9218868437227405311
511            // NEGZERO: -9223372036854775808
512            if (lhsBits < rhsBits) {
513                return -1;
514            } else {
515                return +1;
516            }
517        }
518        
519        /**
520         * <p>Compares two floats for order.</p>
521         *
522         * <p>This method is more comprehensive than the standard Java greater than,
523         * less than and equals operators.</p>
524         * <ul>
525         *  <li>It returns <code>-1</code> if the first value is less than the second.
526         *  <li>It returns <code>+1</code> if the first value is greater than the second.
527         *  <li>It returns <code>0</code> if the values are equal.
528         * </ul>
529         *
530         * <p> The ordering is as follows, largest to smallest:
531         * <ul>
532         * <li>NaN
533         * <li>Positive infinity
534         * <li>Maximum float
535         * <li>Normal positive numbers
536         * <li>+0.0
537         * <li>-0.0
538         * <li>Normal negative numbers
539         * <li>Minimum float (-Float.MAX_VALUE)
540         * <li>Negative infinity
541         * </ul>
542         *
543         * <p>Comparing <code>NaN</code> with <code>NaN</code> will return
544         * <code>0</code>.</p>
545         * 
546         * @param lhs  the first <code>float</code>
547         * @param rhs  the second <code>float</code>
548         * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
549         *  <code>0</code> if equal to rhs
550         */
551        public static int compare(float lhs, float rhs) {
552            if (lhs < rhs) {
553                return -1;
554            }
555            if (lhs > rhs) {
556                return +1;
557            }
558            //Need to compare bits to handle 0.0 == -0.0 being true
559            // compare should put -0.0 < +0.0
560            // Two NaNs are also == for compare purposes
561            // where NaN == NaN is false
562            int lhsBits = Float.floatToIntBits(lhs);
563            int rhsBits = Float.floatToIntBits(rhs);
564            if (lhsBits == rhsBits) {
565                return 0;
566            }
567            //Something exotic! A comparison to NaN or 0.0 vs -0.0
568            //Fortunately NaN's int is > than everything else
569            //Also negzeros bits < poszero
570            //NAN: 2143289344
571            //MAX: 2139095039
572            //NEGZERO: -2147483648
573            if (lhsBits < rhsBits) {
574                return -1;
575            } else {
576                return +1;
577            }
578        }
579        
580        //--------------------------------------------------------------------
581        
582        /**
583         * <p>Checks whether the <code>String</code> contains only
584         * digit characters.</p>
585         *
586         * <p><code>Null</code> and empty String will return
587         * <code>false</code>.</p>
588         *
589         * @param str  the <code>String</code> to check
590         * @return <code>true</code> if str contains only unicode numeric
591         */
592        public static boolean isDigits(String str) {
593            if ((str == null) || (str.length() == 0)) {
594                return false;
595            }
596            for (int i = 0; i < str.length(); i++) {
597                if (!Character.isDigit(str.charAt(i))) {
598                    return false;
599                }
600            }
601            return true;
602        }
603    
604        /**
605         * <p>Checks whether the String a valid Java number.</p>
606         *
607         * <p>Valid numbers include hexadecimal marked with the <code>0x</code>
608         * qualifier, scientific notation and numbers marked with a type
609         * qualifier (e.g. 123L).</p>
610         *
611         * <p><code>Null</code> and empty String will return
612         * <code>false</code>.</p>
613         *
614         * @param str  the <code>String</code> to check
615         * @return <code>true</code> if the string is a correctly formatted number
616         */
617        public static boolean isNumber(String str) {
618            if (StringUtils.isEmpty(str)) {
619                return false;
620            }
621            char[] chars = str.toCharArray();
622            int sz = chars.length;
623            boolean hasExp = false;
624            boolean hasDecPoint = false;
625            boolean allowSigns = false;
626            boolean foundDigit = false;
627            // deal with any possible sign up front
628            int start = (chars[0] == '-') ? 1 : 0;
629            if (sz > start + 1) {
630                if (chars[start] == '0' && chars[start + 1] == 'x') {
631                    int i = start + 2;
632                    if (i == sz) {
633                        return false; // str == "0x"
634                    }
635                    // checking hex (it can't be anything else)
636                    for (; i < chars.length; i++) {
637                        if ((chars[i] < '0' || chars[i] > '9')
638                            && (chars[i] < 'a' || chars[i] > 'f')
639                            && (chars[i] < 'A' || chars[i] > 'F')) {
640                            return false;
641                        }
642                    }
643                    return true;
644                }
645            }
646            sz--; // don't want to loop to the last char, check it afterwords
647                  // for type qualifiers
648            int i = start;
649            // loop to the next to last char or to the last char if we need another digit to
650            // make a valid number (e.g. chars[0..5] = "1234E")
651            while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
652                if (chars[i] >= '0' && chars[i] <= '9') {
653                    foundDigit = true;
654                    allowSigns = false;
655    
656                } else if (chars[i] == '.') {
657                    if (hasDecPoint || hasExp) {
658                        // two decimal points or dec in exponent   
659                        return false;
660                    }
661                    hasDecPoint = true;
662                } else if (chars[i] == 'e' || chars[i] == 'E') {
663                    // we've already taken care of hex.
664                    if (hasExp) {
665                        // two E's
666                        return false;
667                    }
668                    if (!foundDigit) {
669                        return false;
670                    }
671                    hasExp = true;
672                    allowSigns = true;
673                } else if (chars[i] == '+' || chars[i] == '-') {
674                    if (!allowSigns) {
675                        return false;
676                    }
677                    allowSigns = false;
678                    foundDigit = false; // we need a digit after the E
679                } else {
680                    return false;
681                }
682                i++;
683            }
684            if (i < chars.length) {
685                if (chars[i] >= '0' && chars[i] <= '9') {
686                    // no type qualifier, OK
687                    return true;
688                }
689                if (chars[i] == 'e' || chars[i] == 'E') {
690                    // can't have an E at the last byte
691                    return false;
692                }
693                if (!allowSigns
694                    && (chars[i] == 'd'
695                        || chars[i] == 'D'
696                        || chars[i] == 'f'
697                        || chars[i] == 'F')) {
698                    return foundDigit;
699                }
700                if (chars[i] == 'l'
701                    || chars[i] == 'L') {
702                    // not allowing L with an exponent
703                    return foundDigit && !hasExp;
704                }
705                // last character is illegal
706                return false;
707            }
708            // allowSigns is true iff the val ends in 'E'
709            // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
710            return !allowSigns && foundDigit;
711        }
712    }