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 }