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 }