KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > lang > NumberUtils


1 /*
2  * Copyright 2002-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.lang;
17
18 import java.math.BigDecimal JavaDoc;
19 import java.math.BigInteger JavaDoc;
20
21 /**
22  * <p>Provides extra functionality for Java Number classes.</p>
23  *
24  * @author <a HREF="mailto:bayard@generationjava.com">Henri Yandell</a>
25  * @author <a HREF="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
26  * @author Stephen Colebourne
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 161243 2005-04-14 04:30:28Z ggregory $
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      */

46     public NumberUtils() {
47     }
48
49     //--------------------------------------------------------------------
50

51     /**
52      * <p>Convert a <code>String</code> to an <code>int</code>, returning
53      * <code>zero</code> if the conversion fails.</p>
54      *
55      * @param str the string to convert
56      * @return the int represented by the string, or <code>zero</code> if
57      * conversion fails
58      */

59     public static int stringToInt(String JavaDoc str) {
60         return stringToInt(str, 0);
61     }
62
63     /**
64      * <p>Convert a <code>String</code> to an <code>int</code>, returning a
65      * default value if the conversion fails.</p>
66      *
67      * @param str the string to convert
68      * @param defaultValue the default value
69      * @return the int represented by the string, or the default if conversion fails
70      */

71     public static int stringToInt(String JavaDoc str, int defaultValue) {
72         try {
73             return Integer.parseInt(str);
74         } catch (NumberFormatException JavaDoc nfe) {
75             return defaultValue;
76         }
77     }
78
79     //--------------------------------------------------------------------
80

81     // must handle Long, Float, Integer, Float, Short,
82
// BigDecimal, BigInteger and Byte
83
// useful methods:
84
// Byte.decode(String)
85
// Byte.valueOf(String,int radix)
86
// Byte.valueOf(String)
87
// Double.valueOf(String)
88
// Float.valueOf(String)
89
// new Float(String)
90
// Integer.valueOf(String,int radix)
91
// Integer.valueOf(String)
92
// Integer.decode(String)
93
// Integer.getInteger(String)
94
// Integer.getInteger(String,int val)
95
// Integer.getInteger(String,Integer val)
96
// new Integer(String)
97
// new Double(String)
98
// new Byte(String)
99
// new Long(String)
100
// Long.getLong(String)
101
// Long.getLong(String,int)
102
// Long.getLong(String,Integer)
103
// Long.valueOf(String,int)
104
// Long.valueOf(String)
105
// new Short(String)
106
// Short.decode(String)
107
// Short.valueOf(String,int)
108
// Short.valueOf(String)
109
// new BigDecimal(String)
110
// new BigInteger(String)
111
// new BigInteger(String,int radix)
112
// Possible inputs:
113
// 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
114
// plus minus everything. Prolly more. A lot are not separable.
115

116     /**
117      * <p>Turns a string value into a java.lang.Number.</p>
118      *
119      * <p>First, the value is examined for a type qualifier on the end
120      * (<code>'f','F','d','D','l','L'</code>). If it is found, it starts
121      * trying to create successively larger types from the type specified
122      * until one is found that can hold the value.</p>
123      *
124      * <p>If a type specifier is not found, it will check for a decimal point
125      * and then try successively larger types from <code>Integer</code> to
126      * <code>BigInteger</code> and from <code>Float</code> to
127      * <code>BigDecimal</code>.</p>
128      *
129      * <p>If the string starts with <code>0x</code> or <code>-0x</code>, it
130      * will be interpreted as a hexadecimal integer. Values with leading
131      * <code>0</code>'s will not be interpreted as octal.</p>
132      *
133      * @param val String containing a number
134      * @return Number created from the string
135      * @throws NumberFormatException if the value cannot be converted
136      */

137     public static Number JavaDoc createNumber(String JavaDoc val) throws NumberFormatException JavaDoc {
138         if (val == null) {
139             return null;
140         }
141         if (val.length() == 0) {
142             throw new NumberFormatException JavaDoc("\"\" is not a valid number.");
143         }
144         if (val.startsWith("--")) {
145             // this is protection for poorness in java.lang.BigDecimal.
146
// it accepts this as a legal value, but it does not appear
147
// to be in specification of class. OS X Java parses it to
148
// a wrong value.
149
return null;
150         }
151         if (val.startsWith("0x") || val.startsWith("-0x")) {
152             return createInteger(val);
153         }
154         char lastChar = val.charAt(val.length() - 1);
155         String JavaDoc mant;
156         String JavaDoc dec;
157         String JavaDoc exp;
158         int decPos = val.indexOf('.');
159         int expPos = val.indexOf('e') + val.indexOf('E') + 1;
160
161         if (decPos > -1) {
162
163             if (expPos > -1) {
164                 if (expPos < decPos) {
165                     throw new NumberFormatException JavaDoc(val + " is not a valid number.");
166                 }
167                 dec = val.substring(decPos + 1, expPos);
168             } else {
169                 dec = val.substring(decPos + 1);
170             }
171             mant = val.substring(0, decPos);
172         } else {
173             if (expPos > -1) {
174                 mant = val.substring(0, expPos);
175             } else {
176                 mant = val;
177             }
178             dec = null;
179         }
180         if (!Character.isDigit(lastChar)) {
181             if (expPos > -1 && expPos < val.length() - 1) {
182                 exp = val.substring(expPos + 1, val.length() - 1);
183             } else {
184                 exp = null;
185             }
186             //Requesting a specific type..
187
String JavaDoc numeric = val.substring(0, val.length() - 1);
188             boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
189             switch (lastChar) {
190                 case 'l' :
191                 case 'L' :
192                     if (dec == null
193                         && exp == null
194                         && isDigits(numeric.substring(1))
195                         && (numeric.charAt(0) == '-' || Character.isDigit(numeric.charAt(0)))) {
196                         try {
197                             return createLong(numeric);
198                         } catch (NumberFormatException JavaDoc nfe) {
199                             //Too big for a long
200
}
201                         return createBigInteger(numeric);
202
203                     }
204                     throw new NumberFormatException JavaDoc(val + " is not a valid number.");
205                 case 'f' :
206                 case 'F' :
207                     try {
208                         Float JavaDoc 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 JavaDoc nfe) {
216                     }
217                     //Fall through
218
case 'd' :
219                 case 'D' :
220                     try {
221                         Double JavaDoc d = NumberUtils.createDouble(numeric);
222                         if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
223                             return d;
224                         }
225                     } catch (NumberFormatException JavaDoc nfe) {
226                     }
227                     try {
228                         return createBigDecimal(numeric);
229                     } catch (NumberFormatException JavaDoc e) {
230                     }
231                     //Fall through
232
default :
233                     throw new NumberFormatException JavaDoc(val + " is not a valid number.");
234
235             }
236         } else {
237             //User doesn't have a preference on the return type, so let's start
238
//small and go from there...
239
if (expPos > -1 && expPos < val.length() - 1) {
240                 exp = val.substring(expPos + 1, val.length());
241             } else {
242                 exp = null;
243             }
244             if (dec == null && exp == null) {
245                 //Must be an int,long,bigint
246
try {
247                     return createInteger(val);
248                 } catch (NumberFormatException JavaDoc nfe) {
249                 }
250                 try {
251                     return createLong(val);
252                 } catch (NumberFormatException JavaDoc nfe) {
253                 }
254                 return createBigInteger(val);
255
256             } else {
257                 //Must be a float,double,BigDec
258
boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
259                 try {
260                     Float JavaDoc f = createFloat(val);
261                     if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
262                         return f;
263                     }
264                 } catch (NumberFormatException JavaDoc nfe) {
265                 }
266                 try {
267                     Double JavaDoc d = createDouble(val);
268                     if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
269                         return d;
270                     }
271                 } catch (NumberFormatException JavaDoc nfe) {
272                 }
273
274                 return createBigDecimal(val);
275
276             }
277
278         }
279     }
280
281     /**
282      * <p>Utility method for {@link #createNumber(java.lang.String)}.</p>
283      *
284      * <p>Returns <code>true</code> if s is <code>null</code>.</p>
285      *
286      * @param s the String to check
287      * @return if it is all zeros or <code>null</code>
288      */

289     private static boolean isAllZeros(String JavaDoc s) {
290         if (s == null) {
291             return true;
292         }
293         for (int i = s.length() - 1; i >= 0; i--) {
294             if (s.charAt(i) != '0') {
295                 return false;
296             }
297         }
298         return s.length() > 0;
299     }
300
301     //--------------------------------------------------------------------
302

303     /**
304      * <p>Convert a <code>String</code> to a <code>Float</code>.</p>
305      *
306      * @param val a <code>String</code> to convert
307      * @return converted <code>Float</code>
308      * @throws NumberFormatException if the value cannot be converted
309      */

310     public static Float JavaDoc createFloat(String JavaDoc val) {
311         return Float.valueOf(val);
312     }
313
314     /**
315      * <p>Convert a <code>String</code> to a <code>Double</code>.</p>
316      *
317      * @param val a <code>String</code> to convert
318      * @return converted <code>Double</code>
319      * @throws NumberFormatException if the value cannot be converted
320      */

321     public static Double JavaDoc createDouble(String JavaDoc val) {
322         return Double.valueOf(val);
323     }
324
325     /**
326      * <p>Convert a <code>String</code> to a <code>Integer</code>, handling
327      * hex and octal notations.</p>
328      *
329      * @param val a <code>String</code> to convert
330      * @return converted <code>Integer</code>
331      * @throws NumberFormatException if the value cannot be converted
332      */

333     public static Integer JavaDoc createInteger(String JavaDoc val) {
334         // decode() handles 0xAABD and 0777 (hex and octal) as well.
335
return Integer.decode(val);
336     }
337
338     /**
339      * <p>Convert a <code>String</code> to a <code>Long</code>.</p>
340      *
341      * @param val a <code>String</code> to convert
342      * @return converted <code>Long</code>
343      * @throws NumberFormatException if the value cannot be converted
344      */

345     public static Long JavaDoc createLong(String JavaDoc val) {
346         return Long.valueOf(val);
347     }
348
349     /**
350      * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p>
351      *
352      * @param val a <code>String</code> to convert
353      * @return converted <code>BigInteger</code>
354      * @throws NumberFormatException if the value cannot be converted
355      */

356     public static BigInteger JavaDoc createBigInteger(String JavaDoc val) {
357         BigInteger JavaDoc bi = new BigInteger JavaDoc(val);
358         return bi;
359     }
360
361     /**
362      * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p>
363      *
364      * @param val a <code>String</code> to convert
365      * @return converted <code>BigDecimal</code>
366      * @throws NumberFormatException if the value cannot be converted
367      */

368     public static BigDecimal JavaDoc createBigDecimal(String JavaDoc val) {
369         BigDecimal JavaDoc bd = new BigDecimal JavaDoc(val);
370         return bd;
371     }
372
373     //--------------------------------------------------------------------
374

375     /**
376      * <p>Gets the minimum of three <code>long</code> values.</p>
377      *
378      * @param a value 1
379      * @param b value 2
380      * @param c value 3
381      * @return the smallest of the values
382      */

383     public static long minimum(long a, long b, long c) {
384         if (b < a) {
385             a = b;
386         }
387         if (c < a) {
388             a = c;
389         }
390         return a;
391     }
392
393     /**
394      * <p>Gets the minimum of three <code>int</code> values.</p>
395      *
396      * @param a value 1
397      * @param b value 2
398      * @param c value 3
399      * @return the smallest of the values
400      */

401     public static int minimum(int a, int b, int c) {
402         if (b < a) {
403             a = b;
404         }
405         if (c < a) {
406             a = c;
407         }
408         return a;
409     }
410
411     /**
412      * <p>Gets the maximum of three <code>long</code> values.</p>
413      *
414      * @param a value 1
415      * @param b value 2
416      * @param c value 3
417      * @return the largest of the values
418      */

419     public static long maximum(long a, long b, long c) {
420         if (b > a) {
421             a = b;
422         }
423         if (c > a) {
424             a = c;
425         }
426         return a;
427     }
428
429     /**
430      * <p>Gets the maximum of three <code>int</code> values.</p>
431      *
432      * @param a value 1
433      * @param b value 2
434      * @param c value 3
435      * @return the largest of the values
436      */

437     public static int maximum(int a, int b, int c) {
438         if (b > a) {
439             a = b;
440         }
441         if (c > a) {
442             a = c;
443         }
444         return a;
445     }
446
447     //--------------------------------------------------------------------
448

449     /**
450      * <p>Compares two <code>doubles</code> for order.</p>
451      *
452      * <p>This method is more comprehensive than the standard Java greater
453      * than, less than and equals operators.</p>
454      * <ul>
455      * <li>It returns <code>-1</code> if the first value is less than the second.
456      * <li>It returns <code>+1</code> if the first value is greater than the second.
457      * <li>It returns <code>0</code> if the values are equal.
458      * </ul>
459      *
460      * <p>
461      * The ordering is as follows, largest to smallest:
462      * <ul>
463      * <li>NaN
464      * <li>Positive infinity
465      * <li>Maximum double
466      * <li>Normal positive numbers
467      * <li>+0.0
468      * <li>-0.0
469      * <li>Normal negative numbers
470      * <li>Minimum double (-Double.MAX_VALUE)
471      * <li>Negative infinity
472      * </ul>
473      * </p>
474      *
475      * <p>Comparing <code>NaN</code> with <code>NaN</code> will
476      * return <code>0</code>.</p>
477      *
478      * @param lhs the first <code>double</code>
479      * @param rhs the second <code>double</code>
480      * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
481      * <code>0</code> if equal to rhs
482      */

483     public static int compare(double lhs, double rhs) {
484         if (lhs < rhs) {
485             return -1;
486         }
487         if (lhs > rhs) {
488             return +1;
489         }
490         // Need to compare bits to handle 0.0 == -0.0 being true
491
// compare should put -0.0 < +0.0
492
// Two NaNs are also == for compare purposes
493
// where NaN == NaN is false
494
long lhsBits = Double.doubleToLongBits(lhs);
495         long rhsBits = Double.doubleToLongBits(rhs);
496         if (lhsBits == rhsBits) {
497             return 0;
498         }
499         // Something exotic! A comparison to NaN or 0.0 vs -0.0
500
// Fortunately NaN's long is > than everything else
501
// Also negzeros bits < poszero
502
// NAN: 9221120237041090560
503
// MAX: 9218868437227405311
504
// NEGZERO: -9223372036854775808
505
if (lhsBits < rhsBits) {
506             return -1;
507         } else {
508             return +1;
509         }
510     }
511     
512     /**
513      * <p>Compares two floats for order.</p>
514      *
515      * <p>This method is more comprehensive than the standard Java greater than,
516      * less than and equals operators.</p>
517      * <ul>
518      * <li>It returns <code>-1</code> if the first value is less than the second.
519      * <li>It returns <code>+1</code> if the first value is greater than the second.
520      * <li>It returns <code>0</code> if the values are equal.
521      * </ul>
522      *
523      * <p> The ordering is as follows, largest to smallest:
524      * <ul>
525      * <li>NaN
526      * <li>Positive infinity
527      * <li>Maximum float
528      * <li>Normal positive numbers
529      * <li>+0.0
530      * <li>-0.0
531      * <li>Normal negative numbers
532      * <li>Minimum float (-Float.MAX_VALUE)
533      * <li>Negative infinity
534      * </ul>
535      *
536      * <p>Comparing <code>NaN</code> with <code>NaN</code> will return
537      * <code>0</code>.</p>
538      *
539      * @param lhs the first <code>float</code>
540      * @param rhs the second <code>float</code>
541      * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
542      * <code>0</code> if equal to rhs
543      */

544     public static int compare(float lhs, float rhs) {
545         if (lhs < rhs) {
546             return -1;
547         }
548         if (lhs > rhs) {
549             return +1;
550         }
551         //Need to compare bits to handle 0.0 == -0.0 being true
552
// compare should put -0.0 < +0.0
553
// Two NaNs are also == for compare purposes
554
// where NaN == NaN is false
555
int lhsBits = Float.floatToIntBits(lhs);
556         int rhsBits = Float.floatToIntBits(rhs);
557         if (lhsBits == rhsBits) {
558             return 0;
559         }
560         //Something exotic! A comparison to NaN or 0.0 vs -0.0
561
//Fortunately NaN's int is > than everything else
562
//Also negzeros bits < poszero
563
//NAN: 2143289344
564
//MAX: 2139095039
565
//NEGZERO: -2147483648
566
if (lhsBits < rhsBits) {
567             return -1;
568         } else {
569             return +1;
570         }
571     }
572     
573     //--------------------------------------------------------------------
574

575     /**
576      * <p>Checks whether the <code>String</code> contains only
577      * digit characters.</p>
578      *
579      * <p><code>Null</code> and empty String will return
580      * <code>false</code>.</p>
581      *
582      * @param str the <code>String</code> to check
583      * @return <code>true</code> if str contains only unicode numeric
584      */

585     public static boolean isDigits(String JavaDoc str) {
586         if ((str == null) || (str.length() == 0)) {
587             return false;
588         }
589         for (int i = 0; i < str.length(); i++) {
590             if (!Character.isDigit(str.charAt(i))) {
591                 return false;
592             }
593         }
594         return true;
595     }
596
597     /**
598      * <p>Checks whether the String a valid Java number.</p>
599      *
600      * <p>Valid numbers include hexadecimal marked with the <code>0x</code>
601      * qualifier, scientific notation and numbers marked with a type
602      * qualifier (e.g. 123L).</p>
603      *
604      * <p><code>Null</code> and empty String will return
605      * <code>false</code>.</p>
606      *
607      * @param str the <code>String</code> to check
608      * @return <code>true</code> if the string is a correctly formatted number
609      */

610     public static boolean isNumber(String JavaDoc str) {
611         if (StringUtils.isEmpty(str)) {
612             return false;
613         }
614         char[] chars = str.toCharArray();
615         int sz = chars.length;
616         boolean hasExp = false;
617         boolean hasDecPoint = false;
618         boolean allowSigns = false;
619         boolean foundDigit = false;
620         // deal with any possible sign up front
621
int start = (chars[0] == '-') ? 1 : 0;
622         if (sz > start + 1) {
623             if (chars[start] == '0' && chars[start + 1] == 'x') {
624                 int i = start + 2;
625                 if (i == sz) {
626                     return false; // str == "0x"
627
}
628                 // checking hex (it can't be anything else)
629
for (; i < chars.length; i++) {
630                     if ((chars[i] < '0' || chars[i] > '9')
631                         && (chars[i] < 'a' || chars[i] > 'f')
632                         && (chars[i] < 'A' || chars[i] > 'F')) {
633                         return false;
634                     }
635                 }
636                 return true;
637             }
638         }
639         sz--; // don't want to loop to the last char, check it afterwords
640
// for type qualifiers
641
int i = start;
642         // loop to the next to last char or to the last char if we need another digit to
643
// make a valid number (e.g. chars[0..5] = "1234E")
644
while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
645             if (chars[i] >= '0' && chars[i] <= '9') {
646                 foundDigit = true;
647                 allowSigns = false;
648
649             } else if (chars[i] == '.') {
650                 if (hasDecPoint || hasExp) {
651                     // two decimal points or dec in exponent
652
return false;
653                 }
654                 hasDecPoint = true;
655             } else if (chars[i] == 'e' || chars[i] == 'E') {
656                 // we've already taken care of hex.
657
if (hasExp) {
658                     // two E's
659
return false;
660                 }
661                 if (!foundDigit) {
662                     return false;
663                 }
664                 hasExp = true;
665                 allowSigns = true;
666             } else if (chars[i] == '+' || chars[i] == '-') {
667                 if (!allowSigns) {
668                     return false;
669                 }
670                 allowSigns = false;
671                 foundDigit = false; // we need a digit after the E
672
} else {
673                 return false;
674             }
675             i++;
676         }
677         if (i < chars.length) {
678             if (chars[i] >= '0' && chars[i] <= '9') {
679                 // no type qualifier, OK
680
return true;
681             }
682             if (chars[i] == 'e' || chars[i] == 'E') {
683                 // can't have an E at the last byte
684
return false;
685             }
686             if (!allowSigns
687                 && (chars[i] == 'd'
688                     || chars[i] == 'D'
689                     || chars[i] == 'f'
690                     || chars[i] == 'F')) {
691                 return foundDigit;
692             }
693             if (chars[i] == 'l'
694                 || chars[i] == 'L') {
695                 // not allowing L with an exponent
696
return foundDigit && !hasExp;
697             }
698             // last character is illegal
699
return false;
700         }
701         // allowSigns is true iff the val ends in 'E'
702
// found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
703
return !allowSigns && foundDigit;
704     }
705 }
706
Popular Tags