    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    }