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.math;
018
019 import java.math.BigDecimal;
020 import java.math.BigInteger;
021
022 import org.apache.commons.lang.StringUtils;
023
024 /**
025 * <p>Provides extra functionality for Java Number classes.</p>
026 *
027 * @author Apache Software Foundation
028 * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
029 * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
030 * @author Eric Pugh
031 * @author Phil Steitz
032 * @author Matthew Hawthorne
033 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
034 * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
035 * @since 2.0
036 * @version $Id: NumberUtils.java 905707 2010-02-02 16:59:59Z niallp $
037 */
038 public class NumberUtils {
039
040 /** Reusable Long constant for zero. */
041 public static final Long LONG_ZERO = new Long(0L);
042 /** Reusable Long constant for one. */
043 public static final Long LONG_ONE = new Long(1L);
044 /** Reusable Long constant for minus one. */
045 public static final Long LONG_MINUS_ONE = new Long(-1L);
046 /** Reusable Integer constant for zero. */
047 public static final Integer INTEGER_ZERO = new Integer(0);
048 /** Reusable Integer constant for one. */
049 public static final Integer INTEGER_ONE = new Integer(1);
050 /** Reusable Integer constant for minus one. */
051 public static final Integer INTEGER_MINUS_ONE = new Integer(-1);
052 /** Reusable Short constant for zero. */
053 public static final Short SHORT_ZERO = new Short((short) 0);
054 /** Reusable Short constant for one. */
055 public static final Short SHORT_ONE = new Short((short) 1);
056 /** Reusable Short constant for minus one. */
057 public static final Short SHORT_MINUS_ONE = new Short((short) -1);
058 /** Reusable Byte constant for zero. */
059 public static final Byte BYTE_ZERO = new Byte((byte) 0);
060 /** Reusable Byte constant for one. */
061 public static final Byte BYTE_ONE = new Byte((byte) 1);
062 /** Reusable Byte constant for minus one. */
063 public static final Byte BYTE_MINUS_ONE = new Byte((byte) -1);
064 /** Reusable Double constant for zero. */
065 public static final Double DOUBLE_ZERO = new Double(0.0d);
066 /** Reusable Double constant for one. */
067 public static final Double DOUBLE_ONE = new Double(1.0d);
068 /** Reusable Double constant for minus one. */
069 public static final Double DOUBLE_MINUS_ONE = new Double(-1.0d);
070 /** Reusable Float constant for zero. */
071 public static final Float FLOAT_ZERO = new Float(0.0f);
072 /** Reusable Float constant for one. */
073 public static final Float FLOAT_ONE = new Float(1.0f);
074 /** Reusable Float constant for minus one. */
075 public static final Float FLOAT_MINUS_ONE = new Float(-1.0f);
076
077 /**
078 * <p><code>NumberUtils</code> instances should NOT be constructed in standard programming.
079 * Instead, the class should be used as <code>NumberUtils.toInt("6");</code>.</p>
080 *
081 * <p>This constructor is public to permit tools that require a JavaBean instance
082 * to operate.</p>
083 */
084 public NumberUtils() {
085 super();
086 }
087
088 //-----------------------------------------------------------------------
089 /**
090 * <p>Convert a <code>String</code> to an <code>int</code>, returning
091 * <code>zero</code> if the conversion fails.</p>
092 *
093 * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
094 *
095 * <pre>
096 * NumberUtils.stringToInt(null) = 0
097 * NumberUtils.stringToInt("") = 0
098 * NumberUtils.stringToInt("1") = 1
099 * </pre>
100 *
101 * @param str the string to convert, may be null
102 * @return the int represented by the string, or <code>zero</code> if
103 * conversion fails
104 * @deprecated Use {@link #toInt(String)}
105 * This method will be removed in Commons Lang 3.0
106 */
107 public static int stringToInt(String str) {
108 return toInt(str);
109 }
110
111 /**
112 * <p>Convert a <code>String</code> to an <code>int</code>, returning
113 * <code>zero</code> if the conversion fails.</p>
114 *
115 * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
116 *
117 * <pre>
118 * NumberUtils.toInt(null) = 0
119 * NumberUtils.toInt("") = 0
120 * NumberUtils.toInt("1") = 1
121 * </pre>
122 *
123 * @param str the string to convert, may be null
124 * @return the int represented by the string, or <code>zero</code> if
125 * conversion fails
126 * @since 2.1
127 */
128 public static int toInt(String str) {
129 return toInt(str, 0);
130 }
131
132 /**
133 * <p>Convert a <code>String</code> to an <code>int</code>, returning a
134 * default value if the conversion fails.</p>
135 *
136 * <p>If the string is <code>null</code>, the default value is returned.</p>
137 *
138 * <pre>
139 * NumberUtils.stringToInt(null, 1) = 1
140 * NumberUtils.stringToInt("", 1) = 1
141 * NumberUtils.stringToInt("1", 0) = 1
142 * </pre>
143 *
144 * @param str the string to convert, may be null
145 * @param defaultValue the default value
146 * @return the int represented by the string, or the default if conversion fails
147 * @deprecated Use {@link #toInt(String, int)}
148 * This method will be removed in Commons Lang 3.0
149 */
150 public static int stringToInt(String str, int defaultValue) {
151 return toInt(str, defaultValue);
152 }
153
154 /**
155 * <p>Convert a <code>String</code> to an <code>int</code>, returning a
156 * default value if the conversion fails.</p>
157 *
158 * <p>If the string is <code>null</code>, the default value is returned.</p>
159 *
160 * <pre>
161 * NumberUtils.toInt(null, 1) = 1
162 * NumberUtils.toInt("", 1) = 1
163 * NumberUtils.toInt("1", 0) = 1
164 * </pre>
165 *
166 * @param str the string to convert, may be null
167 * @param defaultValue the default value
168 * @return the int represented by the string, or the default if conversion fails
169 * @since 2.1
170 */
171 public static int toInt(String str, int defaultValue) {
172 if(str == null) {
173 return defaultValue;
174 }
175 try {
176 return Integer.parseInt(str);
177 } catch (NumberFormatException nfe) {
178 return defaultValue;
179 }
180 }
181
182 /**
183 * <p>Convert a <code>String</code> to a <code>long</code>, returning
184 * <code>zero</code> if the conversion fails.</p>
185 *
186 * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
187 *
188 * <pre>
189 * NumberUtils.toLong(null) = 0L
190 * NumberUtils.toLong("") = 0L
191 * NumberUtils.toLong("1") = 1L
192 * </pre>
193 *
194 * @param str the string to convert, may be null
195 * @return the long represented by the string, or <code>0</code> if
196 * conversion fails
197 * @since 2.1
198 */
199 public static long toLong(String str) {
200 return toLong(str, 0L);
201 }
202
203 /**
204 * <p>Convert a <code>String</code> to a <code>long</code>, returning a
205 * default value if the conversion fails.</p>
206 *
207 * <p>If the string is <code>null</code>, the default value is returned.</p>
208 *
209 * <pre>
210 * NumberUtils.toLong(null, 1L) = 1L
211 * NumberUtils.toLong("", 1L) = 1L
212 * NumberUtils.toLong("1", 0L) = 1L
213 * </pre>
214 *
215 * @param str the string to convert, may be null
216 * @param defaultValue the default value
217 * @return the long represented by the string, or the default if conversion fails
218 * @since 2.1
219 */
220 public static long toLong(String str, long defaultValue) {
221 if (str == null) {
222 return defaultValue;
223 }
224 try {
225 return Long.parseLong(str);
226 } catch (NumberFormatException nfe) {
227 return defaultValue;
228 }
229 }
230
231 /**
232 * <p>Convert a <code>String</code> to a <code>float</code>, returning
233 * <code>0.0f</code> if the conversion fails.</p>
234 *
235 * <p>If the string <code>str</code> is <code>null</code>,
236 * <code>0.0f</code> is returned.</p>
237 *
238 * <pre>
239 * NumberUtils.toFloat(null) = 0.0f
240 * NumberUtils.toFloat("") = 0.0f
241 * NumberUtils.toFloat("1.5") = 1.5f
242 * </pre>
243 *
244 * @param str the string to convert, may be <code>null</code>
245 * @return the float represented by the string, or <code>0.0f</code>
246 * if conversion fails
247 * @since 2.1
248 */
249 public static float toFloat(String str) {
250 return toFloat(str, 0.0f);
251 }
252
253 /**
254 * <p>Convert a <code>String</code> to a <code>float</code>, returning a
255 * default value if the conversion fails.</p>
256 *
257 * <p>If the string <code>str</code> is <code>null</code>, the default
258 * value is returned.</p>
259 *
260 * <pre>
261 * NumberUtils.toFloat(null, 1.1f) = 1.0f
262 * NumberUtils.toFloat("", 1.1f) = 1.1f
263 * NumberUtils.toFloat("1.5", 0.0f) = 1.5f
264 * </pre>
265 *
266 * @param str the string to convert, may be <code>null</code>
267 * @param defaultValue the default value
268 * @return the float represented by the string, or defaultValue
269 * if conversion fails
270 * @since 2.1
271 */
272 public static float toFloat(String str, float defaultValue) {
273 if (str == null) {
274 return defaultValue;
275 }
276 try {
277 return Float.parseFloat(str);
278 } catch (NumberFormatException nfe) {
279 return defaultValue;
280 }
281 }
282
283 /**
284 * <p>Convert a <code>String</code> to a <code>double</code>, returning
285 * <code>0.0d</code> if the conversion fails.</p>
286 *
287 * <p>If the string <code>str</code> is <code>null</code>,
288 * <code>0.0d</code> is returned.</p>
289 *
290 * <pre>
291 * NumberUtils.toDouble(null) = 0.0d
292 * NumberUtils.toDouble("") = 0.0d
293 * NumberUtils.toDouble("1.5") = 1.5d
294 * </pre>
295 *
296 * @param str the string to convert, may be <code>null</code>
297 * @return the double represented by the string, or <code>0.0d</code>
298 * if conversion fails
299 * @since 2.1
300 */
301 public static double toDouble(String str) {
302 return toDouble(str, 0.0d);
303 }
304
305 /**
306 * <p>Convert a <code>String</code> to a <code>double</code>, returning a
307 * default value if the conversion fails.</p>
308 *
309 * <p>If the string <code>str</code> is <code>null</code>, the default
310 * value is returned.</p>
311 *
312 * <pre>
313 * NumberUtils.toDouble(null, 1.1d) = 1.1d
314 * NumberUtils.toDouble("", 1.1d) = 1.1d
315 * NumberUtils.toDouble("1.5", 0.0d) = 1.5d
316 * </pre>
317 *
318 * @param str the string to convert, may be <code>null</code>
319 * @param defaultValue the default value
320 * @return the double represented by the string, or defaultValue
321 * if conversion fails
322 * @since 2.1
323 */
324 public static double toDouble(String str, double defaultValue) {
325 if (str == null) {
326 return defaultValue;
327 }
328 try {
329 return Double.parseDouble(str);
330 } catch (NumberFormatException nfe) {
331 return defaultValue;
332 }
333 }
334
335 //-----------------------------------------------------------------------
336 /**
337 * <p>Convert a <code>String</code> to a <code>byte</code>, returning
338 * <code>zero</code> if the conversion fails.</p>
339 *
340 * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
341 *
342 * <pre>
343 * NumberUtils.toByte(null) = 0
344 * NumberUtils.toByte("") = 0
345 * NumberUtils.toByte("1") = 1
346 * </pre>
347 *
348 * @param str the string to convert, may be null
349 * @return the byte represented by the string, or <code>zero</code> if
350 * conversion fails
351 * @since 2.5
352 */
353 public static byte toByte(String str) {
354 return toByte(str, (byte) 0);
355 }
356
357 /**
358 * <p>Convert a <code>String</code> to a <code>byte</code>, returning a
359 * default value if the conversion fails.</p>
360 *
361 * <p>If the string is <code>null</code>, the default value is returned.</p>
362 *
363 * <pre>
364 * NumberUtils.toByte(null, 1) = 1
365 * NumberUtils.toByte("", 1) = 1
366 * NumberUtils.toByte("1", 0) = 1
367 * </pre>
368 *
369 * @param str the string to convert, may be null
370 * @param defaultValue the default value
371 * @return the byte represented by the string, or the default if conversion fails
372 * @since 2.5
373 */
374 public static byte toByte(String str, byte defaultValue) {
375 if(str == null) {
376 return defaultValue;
377 }
378 try {
379 return Byte.parseByte(str);
380 } catch (NumberFormatException nfe) {
381 return defaultValue;
382 }
383 }
384
385 /**
386 * <p>Convert a <code>String</code> to a <code>short</code>, returning
387 * <code>zero</code> if the conversion fails.</p>
388 *
389 * <p>If the string is <code>null</code>, <code>zero</code> is returned.</p>
390 *
391 * <pre>
392 * NumberUtils.toShort(null) = 0
393 * NumberUtils.toShort("") = 0
394 * NumberUtils.toShort("1") = 1
395 * </pre>
396 *
397 * @param str the string to convert, may be null
398 * @return the short represented by the string, or <code>zero</code> if
399 * conversion fails
400 * @since 2.5
401 */
402 public static short toShort(String str) {
403 return toShort(str, (short) 0);
404 }
405
406 /**
407 * <p>Convert a <code>String</code> to an <code>short</code>, returning a
408 * default value if the conversion fails.</p>
409 *
410 * <p>If the string is <code>null</code>, the default value is returned.</p>
411 *
412 * <pre>
413 * NumberUtils.toShort(null, 1) = 1
414 * NumberUtils.toShort("", 1) = 1
415 * NumberUtils.toShort("1", 0) = 1
416 * </pre>
417 *
418 * @param str the string to convert, may be null
419 * @param defaultValue the default value
420 * @return the short represented by the string, or the default if conversion fails
421 * @since 2.5
422 */
423 public static short toShort(String str, short defaultValue) {
424 if(str == null) {
425 return defaultValue;
426 }
427 try {
428 return Short.parseShort(str);
429 } catch (NumberFormatException nfe) {
430 return defaultValue;
431 }
432 }
433
434 //-----------------------------------------------------------------------
435 // must handle Long, Float, Integer, Float, Short,
436 // BigDecimal, BigInteger and Byte
437 // useful methods:
438 // Byte.decode(String)
439 // Byte.valueOf(String,int radix)
440 // Byte.valueOf(String)
441 // Double.valueOf(String)
442 // Float.valueOf(String)
443 // new Float(String)
444 // Integer.valueOf(String,int radix)
445 // Integer.valueOf(String)
446 // Integer.decode(String)
447 // Integer.getInteger(String)
448 // Integer.getInteger(String,int val)
449 // Integer.getInteger(String,Integer val)
450 // new Integer(String)
451 // new Double(String)
452 // new Byte(String)
453 // new Long(String)
454 // Long.getLong(String)
455 // Long.getLong(String,int)
456 // Long.getLong(String,Integer)
457 // Long.valueOf(String,int)
458 // Long.valueOf(String)
459 // new Short(String)
460 // Short.decode(String)
461 // Short.valueOf(String,int)
462 // Short.valueOf(String)
463 // new BigDecimal(String)
464 // new BigInteger(String)
465 // new BigInteger(String,int radix)
466 // Possible inputs:
467 // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
468 // plus minus everything. Prolly more. A lot are not separable.
469
470 /**
471 * <p>Turns a string value into a java.lang.Number.</p>
472 *
473 * <p>First, the value is examined for a type qualifier on the end
474 * (<code>'f','F','d','D','l','L'</code>). If it is found, it starts
475 * trying to create successively larger types from the type specified
476 * until one is found that can represent the value.</p>
477 *
478 * <p>If a type specifier is not found, it will check for a decimal point
479 * and then try successively larger types from <code>Integer</code> to
480 * <code>BigInteger</code> and from <code>Float</code> to
481 * <code>BigDecimal</code>.</p>
482 *
483 * <p>If the string starts with <code>0x</code> or <code>-0x</code>, it
484 * will be interpreted as a hexadecimal integer. Values with leading
485 * <code>0</code>'s will not be interpreted as octal.</p>
486 *
487 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
488 *
489 * <p>This method does not trim the input string, i.e., strings with leading
490 * or trailing spaces will generate NumberFormatExceptions.</p>
491 *
492 * @param str String containing a number, may be null
493 * @return Number created from the string
494 * @throws NumberFormatException if the value cannot be converted
495 */
496 public static Number createNumber(String str) throws NumberFormatException {
497 if (str == null) {
498 return null;
499 }
500 if (StringUtils.isBlank(str)) {
501 throw new NumberFormatException("A blank string is not a valid number");
502 }
503 if (str.startsWith("--")) {
504 // this is protection for poorness in java.lang.BigDecimal.
505 // it accepts this as a legal value, but it does not appear
506 // to be in specification of class. OS X Java parses it to
507 // a wrong value.
508 return null;
509 }
510 if (str.startsWith("0x") || str.startsWith("-0x")) {
511 return createInteger(str);
512 }
513 char lastChar = str.charAt(str.length() - 1);
514 String mant;
515 String dec;
516 String exp;
517 int decPos = str.indexOf('.');
518 int expPos = str.indexOf('e') + str.indexOf('E') + 1;
519
520 if (decPos > -1) {
521
522 if (expPos > -1) {
523 if (expPos < decPos) {
524 throw new NumberFormatException(str + " is not a valid number.");
525 }
526 dec = str.substring(decPos + 1, expPos);
527 } else {
528 dec = str.substring(decPos + 1);
529 }
530 mant = str.substring(0, decPos);
531 } else {
532 if (expPos > -1) {
533 mant = str.substring(0, expPos);
534 } else {
535 mant = str;
536 }
537 dec = null;
538 }
539 if (!Character.isDigit(lastChar) && lastChar != '.') {
540 if (expPos > -1 && expPos < str.length() - 1) {
541 exp = str.substring(expPos + 1, str.length() - 1);
542 } else {
543 exp = null;
544 }
545 //Requesting a specific type..
546 String numeric = str.substring(0, str.length() - 1);
547 boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
548 switch (lastChar) {
549 case 'l' :
550 case 'L' :
551 if (dec == null
552 && exp == null
553 && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) {
554 try {
555 return createLong(numeric);
556 } catch (NumberFormatException nfe) {
557 //Too big for a long
558 }
559 return createBigInteger(numeric);
560
561 }
562 throw new NumberFormatException(str + " is not a valid number.");
563 case 'f' :
564 case 'F' :
565 try {
566 Float f = NumberUtils.createFloat(numeric);
567 if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
568 //If it's too big for a float or the float value = 0 and the string
569 //has non-zeros in it, then float does not have the precision we want
570 return f;
571 }
572
573 } catch (NumberFormatException nfe) {
574 // ignore the bad number
575 }
576 //$FALL-THROUGH$
577 case 'd' :
578 case 'D' :
579 try {
580 Double d = NumberUtils.createDouble(numeric);
581 if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
582 return d;
583 }
584 } catch (NumberFormatException nfe) {
585 // ignore the bad number
586 }
587 try {
588 return createBigDecimal(numeric);
589 } catch (NumberFormatException e) {
590 // ignore the bad number
591 }
592 //$FALL-THROUGH$
593 default :
594 throw new NumberFormatException(str + " is not a valid number.");
595
596 }
597 } else {
598 //User doesn't have a preference on the return type, so let's start
599 //small and go from there...
600 if (expPos > -1 && expPos < str.length() - 1) {
601 exp = str.substring(expPos + 1, str.length());
602 } else {
603 exp = null;
604 }
605 if (dec == null && exp == null) {
606 //Must be an int,long,bigint
607 try {
608 return createInteger(str);
609 } catch (NumberFormatException nfe) {
610 // ignore the bad number
611 }
612 try {
613 return createLong(str);
614 } catch (NumberFormatException nfe) {
615 // ignore the bad number
616 }
617 return createBigInteger(str);
618
619 } else {
620 //Must be a float,double,BigDec
621 boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
622 try {
623 Float f = createFloat(str);
624 if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
625 return f;
626 }
627 } catch (NumberFormatException nfe) {
628 // ignore the bad number
629 }
630 try {
631 Double d = createDouble(str);
632 if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
633 return d;
634 }
635 } catch (NumberFormatException nfe) {
636 // ignore the bad number
637 }
638
639 return createBigDecimal(str);
640
641 }
642 }
643 }
644
645 /**
646 * <p>Utility method for {@link #createNumber(java.lang.String)}.</p>
647 *
648 * <p>Returns <code>true</code> if s is <code>null</code>.</p>
649 *
650 * @param str the String to check
651 * @return if it is all zeros or <code>null</code>
652 */
653 private static boolean isAllZeros(String str) {
654 if (str == null) {
655 return true;
656 }
657 for (int i = str.length() - 1; i >= 0; i--) {
658 if (str.charAt(i) != '0') {
659 return false;
660 }
661 }
662 return str.length() > 0;
663 }
664
665 //-----------------------------------------------------------------------
666 /**
667 * <p>Convert a <code>String</code> to a <code>Float</code>.</p>
668 *
669 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
670 *
671 * @param str a <code>String</code> to convert, may be null
672 * @return converted <code>Float</code>
673 * @throws NumberFormatException if the value cannot be converted
674 */
675 public static Float createFloat(String str) {
676 if (str == null) {
677 return null;
678 }
679 return Float.valueOf(str);
680 }
681
682 /**
683 * <p>Convert a <code>String</code> to a <code>Double</code>.</p>
684 *
685 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
686 *
687 * @param str a <code>String</code> to convert, may be null
688 * @return converted <code>Double</code>
689 * @throws NumberFormatException if the value cannot be converted
690 */
691 public static Double createDouble(String str) {
692 if (str == null) {
693 return null;
694 }
695 return Double.valueOf(str);
696 }
697
698 /**
699 * <p>Convert a <code>String</code> to a <code>Integer</code>, handling
700 * hex and octal notations.</p>
701 *
702 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
703 *
704 * @param str a <code>String</code> to convert, may be null
705 * @return converted <code>Integer</code>
706 * @throws NumberFormatException if the value cannot be converted
707 */
708 public static Integer createInteger(String str) {
709 if (str == null) {
710 return null;
711 }
712 // decode() handles 0xAABD and 0777 (hex and octal) as well.
713 return Integer.decode(str);
714 }
715
716 /**
717 * <p>Convert a <code>String</code> to a <code>Long</code>.</p>
718 *
719 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
720 *
721 * @param str a <code>String</code> to convert, may be null
722 * @return converted <code>Long</code>
723 * @throws NumberFormatException if the value cannot be converted
724 */
725 public static Long createLong(String str) {
726 if (str == null) {
727 return null;
728 }
729 return Long.valueOf(str);
730 }
731
732 /**
733 * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p>
734 *
735 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
736 *
737 * @param str a <code>String</code> to convert, may be null
738 * @return converted <code>BigInteger</code>
739 * @throws NumberFormatException if the value cannot be converted
740 */
741 public static BigInteger createBigInteger(String str) {
742 if (str == null) {
743 return null;
744 }
745 return new BigInteger(str);
746 }
747
748 /**
749 * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p>
750 *
751 * <p>Returns <code>null</code> if the string is <code>null</code>.</p>
752 *
753 * @param str a <code>String</code> to convert, may be null
754 * @return converted <code>BigDecimal</code>
755 * @throws NumberFormatException if the value cannot be converted
756 */
757 public static BigDecimal createBigDecimal(String str) {
758 if (str == null) {
759 return null;
760 }
761 // handle JDK1.3.1 bug where "" throws IndexOutOfBoundsException
762 if (StringUtils.isBlank(str)) {
763 throw new NumberFormatException("A blank string is not a valid number");
764 }
765 return new BigDecimal(str);
766 }
767
768 // Min in array
769 //--------------------------------------------------------------------
770 /**
771 * <p>Returns the minimum value in an array.</p>
772 *
773 * @param array an array, must not be null or empty
774 * @return the minimum value in the array
775 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
776 * @throws IllegalArgumentException if <code>array</code> is empty
777 */
778 public static long min(long[] array) {
779 // Validates input
780 if (array == null) {
781 throw new IllegalArgumentException("The Array must not be null");
782 } else if (array.length == 0) {
783 throw new IllegalArgumentException("Array cannot be empty.");
784 }
785
786 // Finds and returns min
787 long min = array[0];
788 for (int i = 1; i < array.length; i++) {
789 if (array[i] < min) {
790 min = array[i];
791 }
792 }
793
794 return min;
795 }
796
797 /**
798 * <p>Returns the minimum value in an array.</p>
799 *
800 * @param array an array, must not be null or empty
801 * @return the minimum value in the array
802 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
803 * @throws IllegalArgumentException if <code>array</code> is empty
804 */
805 public static int min(int[] array) {
806 // Validates input
807 if (array == null) {
808 throw new IllegalArgumentException("The Array must not be null");
809 } else if (array.length == 0) {
810 throw new IllegalArgumentException("Array cannot be empty.");
811 }
812
813 // Finds and returns min
814 int min = array[0];
815 for (int j = 1; j < array.length; j++) {
816 if (array[j] < min) {
817 min = array[j];
818 }
819 }
820
821 return min;
822 }
823
824 /**
825 * <p>Returns the minimum value in an array.</p>
826 *
827 * @param array an array, must not be null or empty
828 * @return the minimum value in the array
829 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
830 * @throws IllegalArgumentException if <code>array</code> is empty
831 */
832 public static short min(short[] array) {
833 // Validates input
834 if (array == null) {
835 throw new IllegalArgumentException("The Array must not be null");
836 } else if (array.length == 0) {
837 throw new IllegalArgumentException("Array cannot be empty.");
838 }
839
840 // Finds and returns min
841 short min = array[0];
842 for (int i = 1; i < array.length; i++) {
843 if (array[i] < min) {
844 min = array[i];
845 }
846 }
847
848 return min;
849 }
850
851 /**
852 * <p>Returns the minimum value in an array.</p>
853 *
854 * @param array an array, must not be null or empty
855 * @return the minimum value in the array
856 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
857 * @throws IllegalArgumentException if <code>array</code> is empty
858 */
859 public static byte min(byte[] array) {
860 // Validates input
861 if (array == null) {
862 throw new IllegalArgumentException("The Array must not be null");
863 } else if (array.length == 0) {
864 throw new IllegalArgumentException("Array cannot be empty.");
865 }
866
867 // Finds and returns min
868 byte min = array[0];
869 for (int i = 1; i < array.length; i++) {
870 if (array[i] < min) {
871 min = array[i];
872 }
873 }
874
875 return min;
876 }
877
878 /**
879 * <p>Returns the minimum value in an array.</p>
880 *
881 * @param array an array, must not be null or empty
882 * @return the minimum value in the array
883 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
884 * @throws IllegalArgumentException if <code>array</code> is empty
885 * @see IEEE754rUtils#min(double[]) IEEE754rUtils for a version of this method that handles NaN differently
886 */
887 public static double min(double[] array) {
888 // Validates input
889 if (array == null) {
890 throw new IllegalArgumentException("The Array must not be null");
891 } else if (array.length == 0) {
892 throw new IllegalArgumentException("Array cannot be empty.");
893 }
894
895 // Finds and returns min
896 double min = array[0];
897 for (int i = 1; i < array.length; i++) {
898 if (Double.isNaN(array[i])) {
899 return Double.NaN;
900 }
901 if (array[i] < min) {
902 min = array[i];
903 }
904 }
905
906 return min;
907 }
908
909 /**
910 * <p>Returns the minimum value in an array.</p>
911 *
912 * @param array an array, must not be null or empty
913 * @return the minimum value in the array
914 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
915 * @throws IllegalArgumentException if <code>array</code> is empty
916 * @see IEEE754rUtils#min(float[]) IEEE754rUtils for a version of this method that handles NaN differently
917 */
918 public static float min(float[] array) {
919 // Validates input
920 if (array == null) {
921 throw new IllegalArgumentException("The Array must not be null");
922 } else if (array.length == 0) {
923 throw new IllegalArgumentException("Array cannot be empty.");
924 }
925
926 // Finds and returns min
927 float min = array[0];
928 for (int i = 1; i < array.length; i++) {
929 if (Float.isNaN(array[i])) {
930 return Float.NaN;
931 }
932 if (array[i] < min) {
933 min = array[i];
934 }
935 }
936
937 return min;
938 }
939
940 // Max in array
941 //--------------------------------------------------------------------
942 /**
943 * <p>Returns the maximum value in an array.</p>
944 *
945 * @param array an array, must not be null or empty
946 * @return the minimum value in the array
947 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
948 * @throws IllegalArgumentException if <code>array</code> is empty
949 */
950 public static long max(long[] array) {
951 // Validates input
952 if (array == null) {
953 throw new IllegalArgumentException("The Array must not be null");
954 } else if (array.length == 0) {
955 throw new IllegalArgumentException("Array cannot be empty.");
956 }
957
958 // Finds and returns max
959 long max = array[0];
960 for (int j = 1; j < array.length; j++) {
961 if (array[j] > max) {
962 max = array[j];
963 }
964 }
965
966 return max;
967 }
968
969 /**
970 * <p>Returns the maximum value in an array.</p>
971 *
972 * @param array an array, must not be null or empty
973 * @return the minimum value in the array
974 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
975 * @throws IllegalArgumentException if <code>array</code> is empty
976 */
977 public static int max(int[] array) {
978 // Validates input
979 if (array == null) {
980 throw new IllegalArgumentException("The Array must not be null");
981 } else if (array.length == 0) {
982 throw new IllegalArgumentException("Array cannot be empty.");
983 }
984
985 // Finds and returns max
986 int max = array[0];
987 for (int j = 1; j < array.length; j++) {
988 if (array[j] > max) {
989 max = array[j];
990 }
991 }
992
993 return max;
994 }
995
996 /**
997 * <p>Returns the maximum value in an array.</p>
998 *
999 * @param array an array, must not be null or empty
1000 * @return the minimum value in the array
1001 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
1002 * @throws IllegalArgumentException if <code>array</code> is empty
1003 */
1004 public static short max(short[] array) {
1005 // Validates input
1006 if (array == null) {
1007 throw new IllegalArgumentException("The Array must not be null");
1008 } else if (array.length == 0) {
1009 throw new IllegalArgumentException("Array cannot be empty.");
1010 }
1011
1012 // Finds and returns max
1013 short max = array[0];
1014 for (int i = 1; i < array.length; i++) {
1015 if (array[i] > max) {
1016 max = array[i];
1017 }
1018 }
1019
1020 return max;
1021 }
1022
1023 /**
1024 * <p>Returns the maximum value in an array.</p>
1025 *
1026 * @param array an array, must not be null or empty
1027 * @return the minimum value in the array
1028 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
1029 * @throws IllegalArgumentException if <code>array</code> is empty
1030 */
1031 public static byte max(byte[] array) {
1032 // Validates input
1033 if (array == null) {
1034 throw new IllegalArgumentException("The Array must not be null");
1035 } else if (array.length == 0) {
1036 throw new IllegalArgumentException("Array cannot be empty.");
1037 }
1038
1039 // Finds and returns max
1040 byte max = array[0];
1041 for (int i = 1; i < array.length; i++) {
1042 if (array[i] > max) {
1043 max = array[i];
1044 }
1045 }
1046
1047 return max;
1048 }
1049
1050 /**
1051 * <p>Returns the maximum value in an array.</p>
1052 *
1053 * @param array an array, must not be null or empty
1054 * @return the minimum value in the array
1055 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
1056 * @throws IllegalArgumentException if <code>array</code> is empty
1057 * @see IEEE754rUtils#max(double[]) IEEE754rUtils for a version of this method that handles NaN differently
1058 */
1059 public static double max(double[] array) {
1060 // Validates input
1061 if (array== null) {
1062 throw new IllegalArgumentException("The Array must not be null");
1063 } else if (array.length == 0) {
1064 throw new IllegalArgumentException("Array cannot be empty.");
1065 }
1066
1067 // Finds and returns max
1068 double max = array[0];
1069 for (int j = 1; j < array.length; j++) {
1070 if (Double.isNaN(array[j])) {
1071 return Double.NaN;
1072 }
1073 if (array[j] > max) {
1074 max = array[j];
1075 }
1076 }
1077
1078 return max;
1079 }
1080
1081 /**
1082 * <p>Returns the maximum value in an array.</p>
1083 *
1084 * @param array an array, must not be null or empty
1085 * @return the minimum value in the array
1086 * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
1087 * @throws IllegalArgumentException if <code>array</code> is empty
1088 * @see IEEE754rUtils#max(float[]) IEEE754rUtils for a version of this method that handles NaN differently
1089 */
1090 public static float max(float[] array) {
1091 // Validates input
1092 if (array == null) {
1093 throw new IllegalArgumentException("The Array must not be null");
1094 } else if (array.length == 0) {
1095 throw new IllegalArgumentException("Array cannot be empty.");
1096 }
1097
1098 // Finds and returns max
1099 float max = array[0];
1100 for (int j = 1; j < array.length; j++) {
1101 if (Float.isNaN(array[j])) {
1102 return Float.NaN;
1103 }
1104 if (array[j] > max) {
1105 max = array[j];
1106 }
1107 }
1108
1109 return max;
1110 }
1111
1112 // 3 param min
1113 //-----------------------------------------------------------------------
1114 /**
1115 * <p>Gets the minimum of three <code>long</code> values.</p>
1116 *
1117 * @param a value 1
1118 * @param b value 2
1119 * @param c value 3
1120 * @return the smallest of the values
1121 */
1122 public static long min(long a, long b, long c) {
1123 if (b < a) {
1124 a = b;
1125 }
1126 if (c < a) {
1127 a = c;
1128 }
1129 return a;
1130 }
1131
1132 /**
1133 * <p>Gets the minimum of three <code>int</code> values.</p>
1134 *
1135 * @param a value 1
1136 * @param b value 2
1137 * @param c value 3
1138 * @return the smallest of the values
1139 */
1140 public static int min(int a, int b, int c) {
1141 if (b < a) {
1142 a = b;
1143 }
1144 if (c < a) {
1145 a = c;
1146 }
1147 return a;
1148 }
1149
1150 /**
1151 * <p>Gets the minimum of three <code>short</code> values.</p>
1152 *
1153 * @param a value 1
1154 * @param b value 2
1155 * @param c value 3
1156 * @return the smallest of the values
1157 */
1158 public static short min(short a, short b, short c) {
1159 if (b < a) {
1160 a = b;
1161 }
1162 if (c < a) {
1163 a = c;
1164 }
1165 return a;
1166 }
1167
1168 /**
1169 * <p>Gets the minimum of three <code>byte</code> values.</p>
1170 *
1171 * @param a value 1
1172 * @param b value 2
1173 * @param c value 3
1174 * @return the smallest of the values
1175 */
1176 public static byte min(byte a, byte b, byte c) {
1177 if (b < a) {
1178 a = b;
1179 }
1180 if (c < a) {
1181 a = c;
1182 }
1183 return a;
1184 }
1185
1186 /**
1187 * <p>Gets the minimum of three <code>double</code> values.</p>
1188 *
1189 * <p>If any value is <code>NaN</code>, <code>NaN</code> is
1190 * returned. Infinity is handled.</p>
1191 *
1192 * @param a value 1
1193 * @param b value 2
1194 * @param c value 3
1195 * @return the smallest of the values
1196 * @see IEEE754rUtils#min(double, double, double) for a version of this method that handles NaN differently
1197 */
1198 public static double min(double a, double b, double c) {
1199 return Math.min(Math.min(a, b), c);
1200 }
1201
1202 /**
1203 * <p>Gets the minimum of three <code>float</code> values.</p>
1204 *
1205 * <p>If any value is <code>NaN</code>, <code>NaN</code> is
1206 * returned. Infinity is handled.</p>
1207 *
1208 * @param a value 1
1209 * @param b value 2
1210 * @param c value 3
1211 * @return the smallest of the values
1212 * @see IEEE754rUtils#min(float, float, float) for a version of this method that handles NaN differently
1213 */
1214 public static float min(float a, float b, float c) {
1215 return Math.min(Math.min(a, b), c);
1216 }
1217
1218 // 3 param max
1219 //-----------------------------------------------------------------------
1220 /**
1221 * <p>Gets the maximum of three <code>long</code> values.</p>
1222 *
1223 * @param a value 1
1224 * @param b value 2
1225 * @param c value 3
1226 * @return the largest of the values
1227 */
1228 public static long max(long a, long b, long c) {
1229 if (b > a) {
1230 a = b;
1231 }
1232 if (c > a) {
1233 a = c;
1234 }
1235 return a;
1236 }
1237
1238 /**
1239 * <p>Gets the maximum of three <code>int</code> values.</p>
1240 *
1241 * @param a value 1
1242 * @param b value 2
1243 * @param c value 3
1244 * @return the largest of the values
1245 */
1246 public static int max(int a, int b, int c) {
1247 if (b > a) {
1248 a = b;
1249 }
1250 if (c > a) {
1251 a = c;
1252 }
1253 return a;
1254 }
1255
1256 /**
1257 * <p>Gets the maximum of three <code>short</code> values.</p>
1258 *
1259 * @param a value 1
1260 * @param b value 2
1261 * @param c value 3
1262 * @return the largest of the values
1263 */
1264 public static short max(short a, short b, short c) {
1265 if (b > a) {
1266 a = b;
1267 }
1268 if (c > a) {
1269 a = c;
1270 }
1271 return a;
1272 }
1273
1274 /**
1275 * <p>Gets the maximum of three <code>byte</code> values.</p>
1276 *
1277 * @param a value 1
1278 * @param b value 2
1279 * @param c value 3
1280 * @return the largest of the values
1281 */
1282 public static byte max(byte a, byte b, byte c) {
1283 if (b > a) {
1284 a = b;
1285 }
1286 if (c > a) {
1287 a = c;
1288 }
1289 return a;
1290 }
1291
1292 /**
1293 * <p>Gets the maximum of three <code>double</code> values.</p>
1294 *
1295 * <p>If any value is <code>NaN</code>, <code>NaN</code> is
1296 * returned. Infinity is handled.</p>
1297 *
1298 * @param a value 1
1299 * @param b value 2
1300 * @param c value 3
1301 * @return the largest of the values
1302 * @see IEEE754rUtils#max(double, double, double) for a version of this method that handles NaN differently
1303 */
1304 public static double max(double a, double b, double c) {
1305 return Math.max(Math.max(a, b), c);
1306 }
1307
1308 /**
1309 * <p>Gets the maximum of three <code>float</code> values.</p>
1310 *
1311 * <p>If any value is <code>NaN</code>, <code>NaN</code> is
1312 * returned. Infinity is handled.</p>
1313 *
1314 * @param a value 1
1315 * @param b value 2
1316 * @param c value 3
1317 * @return the largest of the values
1318 * @see IEEE754rUtils#max(float, float, float) for a version of this method that handles NaN differently
1319 */
1320 public static float max(float a, float b, float c) {
1321 return Math.max(Math.max(a, b), c);
1322 }
1323
1324 //-----------------------------------------------------------------------
1325 /**
1326 * <p>Compares two <code>doubles</code> for order.</p>
1327 *
1328 * <p>This method is more comprehensive than the standard Java greater
1329 * than, less than and equals operators.</p>
1330 * <ul>
1331 * <li>It returns <code>-1</code> if the first value is less than the second.</li>
1332 * <li>It returns <code>+1</code> if the first value is greater than the second.</li>
1333 * <li>It returns <code>0</code> if the values are equal.</li>
1334 * </ul>
1335 *
1336 * <p>
1337 * The ordering is as follows, largest to smallest:
1338 * <ul>
1339 * <li>NaN
1340 * <li>Positive infinity
1341 * <li>Maximum double
1342 * <li>Normal positive numbers
1343 * <li>+0.0
1344 * <li>-0.0
1345 * <li>Normal negative numbers
1346 * <li>Minimum double (<code>-Double.MAX_VALUE</code>)
1347 * <li>Negative infinity
1348 * </ul>
1349 * </p>
1350 *
1351 * <p>Comparing <code>NaN</code> with <code>NaN</code> will
1352 * return <code>0</code>.</p>
1353 *
1354 * @param lhs the first <code>double</code>
1355 * @param rhs the second <code>double</code>
1356 * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
1357 * <code>0</code> if equal to rhs
1358 */
1359 public static int compare(double lhs, double rhs) {
1360 if (lhs < rhs) {
1361 return -1;
1362 }
1363 if (lhs > rhs) {
1364 return +1;
1365 }
1366 // Need to compare bits to handle 0.0 == -0.0 being true
1367 // compare should put -0.0 < +0.0
1368 // Two NaNs are also == for compare purposes
1369 // where NaN == NaN is false
1370 long lhsBits = Double.doubleToLongBits(lhs);
1371 long rhsBits = Double.doubleToLongBits(rhs);
1372 if (lhsBits == rhsBits) {
1373 return 0;
1374 }
1375 // Something exotic! A comparison to NaN or 0.0 vs -0.0
1376 // Fortunately NaN's long is > than everything else
1377 // Also negzeros bits < poszero
1378 // NAN: 9221120237041090560
1379 // MAX: 9218868437227405311
1380 // NEGZERO: -9223372036854775808
1381 if (lhsBits < rhsBits) {
1382 return -1;
1383 } else {
1384 return +1;
1385 }
1386 }
1387
1388 /**
1389 * <p>Compares two floats for order.</p>
1390 *
1391 * <p>This method is more comprehensive than the standard Java greater than,
1392 * less than and equals operators.</p>
1393 * <ul>
1394 * <li>It returns <code>-1</code> if the first value is less than the second.
1395 * <li>It returns <code>+1</code> if the first value is greater than the second.
1396 * <li>It returns <code>0</code> if the values are equal.
1397 * </ul>
1398 *
1399 * <p> The ordering is as follows, largest to smallest:
1400 * <ul>
1401 * <li>NaN
1402 * <li>Positive infinity
1403 * <li>Maximum float
1404 * <li>Normal positive numbers
1405 * <li>+0.0
1406 * <li>-0.0
1407 * <li>Normal negative numbers
1408 * <li>Minimum float (<code>-Float.MAX_VALUE</code>)
1409 * <li>Negative infinity
1410 * </ul>
1411 *
1412 * <p>Comparing <code>NaN</code> with <code>NaN</code> will return
1413 * <code>0</code>.</p>
1414 *
1415 * @param lhs the first <code>float</code>
1416 * @param rhs the second <code>float</code>
1417 * @return <code>-1</code> if lhs is less, <code>+1</code> if greater,
1418 * <code>0</code> if equal to rhs
1419 */
1420 public static int compare(float lhs, float rhs) {
1421 if (lhs < rhs) {
1422 return -1;
1423 }
1424 if (lhs > rhs) {
1425 return +1;
1426 }
1427 //Need to compare bits to handle 0.0 == -0.0 being true
1428 // compare should put -0.0 < +0.0
1429 // Two NaNs are also == for compare purposes
1430 // where NaN == NaN is false
1431 int lhsBits = Float.floatToIntBits(lhs);
1432 int rhsBits = Float.floatToIntBits(rhs);
1433 if (lhsBits == rhsBits) {
1434 return 0;
1435 }
1436 //Something exotic! A comparison to NaN or 0.0 vs -0.0
1437 //Fortunately NaN's int is > than everything else
1438 //Also negzeros bits < poszero
1439 //NAN: 2143289344
1440 //MAX: 2139095039
1441 //NEGZERO: -2147483648
1442 if (lhsBits < rhsBits) {
1443 return -1;
1444 } else {
1445 return +1;
1446 }
1447 }
1448
1449 //-----------------------------------------------------------------------
1450 /**
1451 * <p>Checks whether the <code>String</code> contains only
1452 * digit characters.</p>
1453 *
1454 * <p><code>Null</code> and empty String will return
1455 * <code>false</code>.</p>
1456 *
1457 * @param str the <code>String</code> to check
1458 * @return <code>true</code> if str contains only unicode numeric
1459 */
1460 public static boolean isDigits(String str) {
1461 if (StringUtils.isEmpty(str)) {
1462 return false;
1463 }
1464 for (int i = 0; i < str.length(); i++) {
1465 if (!Character.isDigit(str.charAt(i))) {
1466 return false;
1467 }
1468 }
1469 return true;
1470 }
1471
1472 /**
1473 * <p>Checks whether the String a valid Java number.</p>
1474 *
1475 * <p>Valid numbers include hexadecimal marked with the <code>0x</code>
1476 * qualifier, scientific notation and numbers marked with a type
1477 * qualifier (e.g. 123L).</p>
1478 *
1479 * <p><code>Null</code> and empty String will return
1480 * <code>false</code>.</p>
1481 *
1482 * @param str the <code>String</code> to check
1483 * @return <code>true</code> if the string is a correctly formatted number
1484 */
1485 public static boolean isNumber(String str) {
1486 if (StringUtils.isEmpty(str)) {
1487 return false;
1488 }
1489 char[] chars = str.toCharArray();
1490 int sz = chars.length;
1491 boolean hasExp = false;
1492 boolean hasDecPoint = false;
1493 boolean allowSigns = false;
1494 boolean foundDigit = false;
1495 // deal with any possible sign up front
1496 int start = (chars[0] == '-') ? 1 : 0;
1497 if (sz > start + 1) {
1498 if (chars[start] == '0' && chars[start + 1] == 'x') {
1499 int i = start + 2;
1500 if (i == sz) {
1501 return false; // str == "0x"
1502 }
1503 // checking hex (it can't be anything else)
1504 for (; i < chars.length; i++) {
1505 if ((chars[i] < '0' || chars[i] > '9')
1506 && (chars[i] < 'a' || chars[i] > 'f')
1507 && (chars[i] < 'A' || chars[i] > 'F')) {
1508 return false;
1509 }
1510 }
1511 return true;
1512 }
1513 }
1514 sz--; // don't want to loop to the last char, check it afterwords
1515 // for type qualifiers
1516 int i = start;
1517 // loop to the next to last char or to the last char if we need another digit to
1518 // make a valid number (e.g. chars[0..5] = "1234E")
1519 while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
1520 if (chars[i] >= '0' && chars[i] <= '9') {
1521 foundDigit = true;
1522 allowSigns = false;
1523
1524 } else if (chars[i] == '.') {
1525 if (hasDecPoint || hasExp) {
1526 // two decimal points or dec in exponent
1527 return false;
1528 }
1529 hasDecPoint = true;
1530 } else if (chars[i] == 'e' || chars[i] == 'E') {
1531 // we've already taken care of hex.
1532 if (hasExp) {
1533 // two E's
1534 return false;
1535 }
1536 if (!foundDigit) {
1537 return false;
1538 }
1539 hasExp = true;
1540 allowSigns = true;
1541 } else if (chars[i] == '+' || chars[i] == '-') {
1542 if (!allowSigns) {
1543 return false;
1544 }
1545 allowSigns = false;
1546 foundDigit = false; // we need a digit after the E
1547 } else {
1548 return false;
1549 }
1550 i++;
1551 }
1552 if (i < chars.length) {
1553 if (chars[i] >= '0' && chars[i] <= '9') {
1554 // no type qualifier, OK
1555 return true;
1556 }
1557 if (chars[i] == 'e' || chars[i] == 'E') {
1558 // can't have an E at the last byte
1559 return false;
1560 }
1561 if (chars[i] == '.') {
1562 if (hasDecPoint || hasExp) {
1563 // two decimal points or dec in exponent
1564 return false;
1565 }
1566 // single trailing decimal point after non-exponent is ok
1567 return foundDigit;
1568 }
1569 if (!allowSigns
1570 && (chars[i] == 'd'
1571 || chars[i] == 'D'
1572 || chars[i] == 'f'
1573 || chars[i] == 'F')) {
1574 return foundDigit;
1575 }
1576 if (chars[i] == 'l'
1577 || chars[i] == 'L') {
1578 // not allowing L with an exponent
1579 return foundDigit && !hasExp;
1580 }
1581 // last character is illegal
1582 return false;
1583 }
1584 // allowSigns is true iff the val ends in 'E'
1585 // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
1586 return !allowSigns && foundDigit;
1587 }
1588
1589 }