001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.lang; 018 019 import java.math.BigDecimal; 020 import java.math.BigInteger; 021 022 /** 023 * <p>Provides extra functionality for Java Number classes.</p> 024 * 025 * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a> 026 * @author Stephen Colebourne 027 * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a> 028 * @author Eric Pugh 029 * @author Phil Steitz 030 * @since 1.0 031 * @version $Id: NumberUtils.java 488819 2006-12-19 21:50:04Z bayard $ 032 * 033 * @deprecated Moved to org.apache.commons.lang.math. 034 * Class will be removed in Commons Lang 3.0. 035 */ 036 public final class NumberUtils { 037 // DEPRECATED CLASS !!! 038 039 /** 040 * <p><code>NumberUtils</code> instances should NOT be constructed in standard programming. 041 * Instead, the class should be used as <code>NumberUtils.stringToInt("6");</code>.</p> 042 * 043 * <p>This constructor is public to permit tools that require a JavaBean instance 044 * to operate.</p> 045 */ 046 public NumberUtils() { 047 super(); 048 } 049 050 //-------------------------------------------------------------------- 051 052 /** 053 * <p>Convert a <code>String</code> to an <code>int</code>, returning 054 * <code>zero</code> if the conversion fails.</p> 055 * 056 * @param str the string to convert 057 * @return the int represented by the string, or <code>zero</code> if 058 * conversion fails 059 */ 060 public static int stringToInt(String str) { 061 return stringToInt(str, 0); 062 } 063 064 /** 065 * <p>Convert a <code>String</code> to an <code>int</code>, returning a 066 * default value if the conversion fails.</p> 067 * 068 * @param str the string to convert 069 * @param defaultValue the default value 070 * @return the int represented by the string, or the default if conversion fails 071 */ 072 public static int stringToInt(String str, int defaultValue) { 073 try { 074 return Integer.parseInt(str); 075 } catch (NumberFormatException nfe) { 076 return defaultValue; 077 } 078 } 079 080 //-------------------------------------------------------------------- 081 082 // must handle Long, Float, Integer, Float, Short, 083 // BigDecimal, BigInteger and Byte 084 // useful methods: 085 // Byte.decode(String) 086 // Byte.valueOf(String,int radix) 087 // Byte.valueOf(String) 088 // Double.valueOf(String) 089 // Float.valueOf(String) 090 // new Float(String) 091 // Integer.valueOf(String,int radix) 092 // Integer.valueOf(String) 093 // Integer.decode(String) 094 // Integer.getInteger(String) 095 // Integer.getInteger(String,int val) 096 // Integer.getInteger(String,Integer val) 097 // new Integer(String) 098 // new Double(String) 099 // new Byte(String) 100 // new Long(String) 101 // Long.getLong(String) 102 // Long.getLong(String,int) 103 // Long.getLong(String,Integer) 104 // Long.valueOf(String,int) 105 // Long.valueOf(String) 106 // new Short(String) 107 // Short.decode(String) 108 // Short.valueOf(String,int) 109 // Short.valueOf(String) 110 // new BigDecimal(String) 111 // new BigInteger(String) 112 // new BigInteger(String,int radix) 113 // Possible inputs: 114 // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd 115 // plus minus everything. Prolly more. A lot are not separable. 116 117 /** 118 * <p>Turns a string value into a java.lang.Number.</p> 119 * 120 * <p>First, the value is examined for a type qualifier on the end 121 * (<code>'f','F','d','D','l','L'</code>). If it is found, it starts 122 * trying to create successively larger types from the type specified 123 * until one is found that can hold the value.</p> 124 * 125 * <p>If a type specifier is not found, it will check for a decimal point 126 * and then try successively larger types from <code>Integer</code> to 127 * <code>BigInteger</code> and from <code>Float</code> to 128 * <code>BigDecimal</code>.</p> 129 * 130 * <p>If the string starts with <code>0x</code> or <code>-0x</code>, it 131 * will be interpreted as a hexadecimal integer. Values with leading 132 * <code>0</code>'s will not be interpreted as octal.</p> 133 * 134 * @param val String containing a number 135 * @return Number created from the string 136 * @throws NumberFormatException if the value cannot be converted 137 */ 138 public static Number createNumber(String val) throws NumberFormatException { 139 if (val == null) { 140 return null; 141 } 142 if (val.length() == 0) { 143 throw new NumberFormatException("\"\" is not a valid number."); 144 } 145 if (val.startsWith("--")) { 146 // this is protection for poorness in java.lang.BigDecimal. 147 // it accepts this as a legal value, but it does not appear 148 // to be in specification of class. OS X Java parses it to 149 // a wrong value. 150 return null; 151 } 152 if (val.startsWith("0x") || val.startsWith("-0x")) { 153 return createInteger(val); 154 } 155 char lastChar = val.charAt(val.length() - 1); 156 String mant; 157 String dec; 158 String exp; 159 int decPos = val.indexOf('.'); 160 int expPos = val.indexOf('e') + val.indexOf('E') + 1; 161 162 if (decPos > -1) { 163 164 if (expPos > -1) { 165 if (expPos < decPos) { 166 throw new NumberFormatException(val + " is not a valid number."); 167 } 168 dec = val.substring(decPos + 1, expPos); 169 } else { 170 dec = val.substring(decPos + 1); 171 } 172 mant = val.substring(0, decPos); 173 } else { 174 if (expPos > -1) { 175 mant = val.substring(0, expPos); 176 } else { 177 mant = val; 178 } 179 dec = null; 180 } 181 if (!Character.isDigit(lastChar)) { 182 if (expPos > -1 && expPos < val.length() - 1) { 183 exp = val.substring(expPos + 1, val.length() - 1); 184 } else { 185 exp = null; 186 } 187 //Requesting a specific type.. 188 String numeric = val.substring(0, val.length() - 1); 189 boolean allZeros = isAllZeros(mant) && isAllZeros(exp); 190 switch (lastChar) { 191 case 'l' : 192 case 'L' : 193 if (dec == null 194 && exp == null 195 && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) { 196 try { 197 return createLong(numeric); 198 } catch (NumberFormatException nfe) { 199 //Too big for a long 200 } 201 return createBigInteger(numeric); 202 203 } 204 throw new NumberFormatException(val + " is not a valid number."); 205 case 'f' : 206 case 'F' : 207 try { 208 Float f = NumberUtils.createFloat(numeric); 209 if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) { 210 //If it's too big for a float or the float value = 0 and the string 211 //has non-zeros in it, then float does not have the precision we want 212 return f; 213 } 214 215 } catch (NumberFormatException e) { 216 // ignore the bad number 217 } 218 //Fall through 219 case 'd' : 220 case 'D' : 221 try { 222 Double d = NumberUtils.createDouble(numeric); 223 if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) { 224 return d; 225 } 226 } catch (NumberFormatException nfe) { 227 // empty catch 228 } 229 try { 230 return createBigDecimal(numeric); 231 } catch (NumberFormatException e) { 232 // empty catch 233 } 234 //Fall through 235 default : 236 throw new NumberFormatException(val + " is not a valid number."); 237 238 } 239 } else { 240 //User doesn't have a preference on the return type, so let's start 241 //small and go from there... 242 if (expPos > -1 && expPos < val.length() - 1) { 243 exp = val.substring(expPos + 1, val.length()); 244 } else { 245 exp = null; 246 } 247 if (dec == null && exp == null) { 248 //Must be an int,long,bigint 249 try { 250 return createInteger(val); 251 } catch (NumberFormatException nfe) { 252 // empty catch 253 } 254 try { 255 return createLong(val); 256 } catch (NumberFormatException nfe) { 257 // empty catch 258 } 259 return createBigInteger(val); 260 261 } else { 262 //Must be a float,double,BigDec 263 boolean allZeros = isAllZeros(mant) && isAllZeros(exp); 264 try { 265 Float f = createFloat(val); 266 if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) { 267 return f; 268 } 269 } catch (NumberFormatException nfe) { 270 // empty catch 271 } 272 try { 273 Double d = createDouble(val); 274 if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) { 275 return d; 276 } 277 } catch (NumberFormatException nfe) { 278 // empty catch 279 } 280 281 return createBigDecimal(val); 282 283 } 284 285 } 286 } 287 288 /** 289 * <p>Utility method for {@link #createNumber(java.lang.String)}.</p> 290 * 291 * <p>Returns <code>true</code> if s is <code>null</code>.</p> 292 * 293 * @param s the String to check 294 * @return if it is all zeros or <code>null</code> 295 */ 296 private static boolean isAllZeros(String s) { 297 if (s == null) { 298 return true; 299 } 300 for (int i = s.length() - 1; i >= 0; i--) { 301 if (s.charAt(i) != '0') { 302 return false; 303 } 304 } 305 return s.length() > 0; 306 } 307 308 //-------------------------------------------------------------------- 309 310 /** 311 * <p>Convert a <code>String</code> to a <code>Float</code>.</p> 312 * 313 * @param val a <code>String</code> to convert 314 * @return converted <code>Float</code> 315 * @throws NumberFormatException if the value cannot be converted 316 */ 317 public static Float createFloat(String val) { 318 return Float.valueOf(val); 319 } 320 321 /** 322 * <p>Convert a <code>String</code> to a <code>Double</code>.</p> 323 * 324 * @param val a <code>String</code> to convert 325 * @return converted <code>Double</code> 326 * @throws NumberFormatException if the value cannot be converted 327 */ 328 public static Double createDouble(String val) { 329 return Double.valueOf(val); 330 } 331 332 /** 333 * <p>Convert a <code>String</code> to a <code>Integer</code>, handling 334 * hex and octal notations.</p> 335 * 336 * @param val a <code>String</code> to convert 337 * @return converted <code>Integer</code> 338 * @throws NumberFormatException if the value cannot be converted 339 */ 340 public static Integer createInteger(String val) { 341 // decode() handles 0xAABD and 0777 (hex and octal) as well. 342 return Integer.decode(val); 343 } 344 345 /** 346 * <p>Convert a <code>String</code> to a <code>Long</code>.</p> 347 * 348 * @param val a <code>String</code> to convert 349 * @return converted <code>Long</code> 350 * @throws NumberFormatException if the value cannot be converted 351 */ 352 public static Long createLong(String val) { 353 return Long.valueOf(val); 354 } 355 356 /** 357 * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p> 358 * 359 * @param val a <code>String</code> to convert 360 * @return converted <code>BigInteger</code> 361 * @throws NumberFormatException if the value cannot be converted 362 */ 363 public static BigInteger createBigInteger(String val) { 364 BigInteger bi = new BigInteger(val); 365 return bi; 366 } 367 368 /** 369 * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p> 370 * 371 * @param val a <code>String</code> to convert 372 * @return converted <code>BigDecimal</code> 373 * @throws NumberFormatException if the value cannot be converted 374 */ 375 public static BigDecimal createBigDecimal(String val) { 376 BigDecimal bd = new BigDecimal(val); 377 return bd; 378 } 379 380 //-------------------------------------------------------------------- 381 382 /** 383 * <p>Gets the minimum of three <code>long</code> values.</p> 384 * 385 * @param a value 1 386 * @param b value 2 387 * @param c value 3 388 * @return the smallest of the values 389 */ 390 public static long minimum(long a, long b, long c) { 391 if (b < a) { 392 a = b; 393 } 394 if (c < a) { 395 a = c; 396 } 397 return a; 398 } 399 400 /** 401 * <p>Gets the minimum of three <code>int</code> values.</p> 402 * 403 * @param a value 1 404 * @param b value 2 405 * @param c value 3 406 * @return the smallest of the values 407 */ 408 public static int minimum(int a, int b, int c) { 409 if (b < a) { 410 a = b; 411 } 412 if (c < a) { 413 a = c; 414 } 415 return a; 416 } 417 418 /** 419 * <p>Gets the maximum of three <code>long</code> values.</p> 420 * 421 * @param a value 1 422 * @param b value 2 423 * @param c value 3 424 * @return the largest of the values 425 */ 426 public static long maximum(long a, long b, long c) { 427 if (b > a) { 428 a = b; 429 } 430 if (c > a) { 431 a = c; 432 } 433 return a; 434 } 435 436 /** 437 * <p>Gets the maximum of three <code>int</code> values.</p> 438 * 439 * @param a value 1 440 * @param b value 2 441 * @param c value 3 442 * @return the largest of the values 443 */ 444 public static int maximum(int a, int b, int c) { 445 if (b > a) { 446 a = b; 447 } 448 if (c > a) { 449 a = c; 450 } 451 return a; 452 } 453 454 //-------------------------------------------------------------------- 455 456 /** 457 * <p>Compares two <code>doubles</code> for order.</p> 458 * 459 * <p>This method is more comprehensive than the standard Java greater 460 * than, less than and equals operators.</p> 461 * <ul> 462 * <li>It returns <code>-1</code> if the first value is less than the second. 463 * <li>It returns <code>+1</code> if the first value is greater than the second. 464 * <li>It returns <code>0</code> if the values are equal. 465 * </ul> 466 * 467 * <p> 468 * The ordering is as follows, largest to smallest: 469 * <ul> 470 * <li>NaN 471 * <li>Positive infinity 472 * <li>Maximum double 473 * <li>Normal positive numbers 474 * <li>+0.0 475 * <li>-0.0 476 * <li>Normal negative numbers 477 * <li>Minimum double (-Double.MAX_VALUE) 478 * <li>Negative infinity 479 * </ul> 480 * </p> 481 * 482 * <p>Comparing <code>NaN</code> with <code>NaN</code> will 483 * return <code>0</code>.</p> 484 * 485 * @param lhs the first <code>double</code> 486 * @param rhs the second <code>double</code> 487 * @return <code>-1</code> if lhs is less, <code>+1</code> if greater, 488 * <code>0</code> if equal to rhs 489 */ 490 public static int compare(double lhs, double rhs) { 491 if (lhs < rhs) { 492 return -1; 493 } 494 if (lhs > rhs) { 495 return +1; 496 } 497 // Need to compare bits to handle 0.0 == -0.0 being true 498 // compare should put -0.0 < +0.0 499 // Two NaNs are also == for compare purposes 500 // where NaN == NaN is false 501 long lhsBits = Double.doubleToLongBits(lhs); 502 long rhsBits = Double.doubleToLongBits(rhs); 503 if (lhsBits == rhsBits) { 504 return 0; 505 } 506 // Something exotic! A comparison to NaN or 0.0 vs -0.0 507 // Fortunately NaN's long is > than everything else 508 // Also negzeros bits < poszero 509 // NAN: 9221120237041090560 510 // MAX: 9218868437227405311 511 // NEGZERO: -9223372036854775808 512 if (lhsBits < rhsBits) { 513 return -1; 514 } else { 515 return +1; 516 } 517 } 518 519 /** 520 * <p>Compares two floats for order.</p> 521 * 522 * <p>This method is more comprehensive than the standard Java greater than, 523 * less than and equals operators.</p> 524 * <ul> 525 * <li>It returns <code>-1</code> if the first value is less than the second. 526 * <li>It returns <code>+1</code> if the first value is greater than the second. 527 * <li>It returns <code>0</code> if the values are equal. 528 * </ul> 529 * 530 * <p> The ordering is as follows, largest to smallest: 531 * <ul> 532 * <li>NaN 533 * <li>Positive infinity 534 * <li>Maximum float 535 * <li>Normal positive numbers 536 * <li>+0.0 537 * <li>-0.0 538 * <li>Normal negative numbers 539 * <li>Minimum float (-Float.MAX_VALUE) 540 * <li>Negative infinity 541 * </ul> 542 * 543 * <p>Comparing <code>NaN</code> with <code>NaN</code> will return 544 * <code>0</code>.</p> 545 * 546 * @param lhs the first <code>float</code> 547 * @param rhs the second <code>float</code> 548 * @return <code>-1</code> if lhs is less, <code>+1</code> if greater, 549 * <code>0</code> if equal to rhs 550 */ 551 public static int compare(float lhs, float rhs) { 552 if (lhs < rhs) { 553 return -1; 554 } 555 if (lhs > rhs) { 556 return +1; 557 } 558 //Need to compare bits to handle 0.0 == -0.0 being true 559 // compare should put -0.0 < +0.0 560 // Two NaNs are also == for compare purposes 561 // where NaN == NaN is false 562 int lhsBits = Float.floatToIntBits(lhs); 563 int rhsBits = Float.floatToIntBits(rhs); 564 if (lhsBits == rhsBits) { 565 return 0; 566 } 567 //Something exotic! A comparison to NaN or 0.0 vs -0.0 568 //Fortunately NaN's int is > than everything else 569 //Also negzeros bits < poszero 570 //NAN: 2143289344 571 //MAX: 2139095039 572 //NEGZERO: -2147483648 573 if (lhsBits < rhsBits) { 574 return -1; 575 } else { 576 return +1; 577 } 578 } 579 580 //-------------------------------------------------------------------- 581 582 /** 583 * <p>Checks whether the <code>String</code> contains only 584 * digit characters.</p> 585 * 586 * <p><code>Null</code> and empty String will return 587 * <code>false</code>.</p> 588 * 589 * @param str the <code>String</code> to check 590 * @return <code>true</code> if str contains only unicode numeric 591 */ 592 public static boolean isDigits(String str) { 593 if ((str == null) || (str.length() == 0)) { 594 return false; 595 } 596 for (int i = 0; i < str.length(); i++) { 597 if (!Character.isDigit(str.charAt(i))) { 598 return false; 599 } 600 } 601 return true; 602 } 603 604 /** 605 * <p>Checks whether the String a valid Java number.</p> 606 * 607 * <p>Valid numbers include hexadecimal marked with the <code>0x</code> 608 * qualifier, scientific notation and numbers marked with a type 609 * qualifier (e.g. 123L).</p> 610 * 611 * <p><code>Null</code> and empty String will return 612 * <code>false</code>.</p> 613 * 614 * @param str the <code>String</code> to check 615 * @return <code>true</code> if the string is a correctly formatted number 616 */ 617 public static boolean isNumber(String str) { 618 if (StringUtils.isEmpty(str)) { 619 return false; 620 } 621 char[] chars = str.toCharArray(); 622 int sz = chars.length; 623 boolean hasExp = false; 624 boolean hasDecPoint = false; 625 boolean allowSigns = false; 626 boolean foundDigit = false; 627 // deal with any possible sign up front 628 int start = (chars[0] == '-') ? 1 : 0; 629 if (sz > start + 1) { 630 if (chars[start] == '0' && chars[start + 1] == 'x') { 631 int i = start + 2; 632 if (i == sz) { 633 return false; // str == "0x" 634 } 635 // checking hex (it can't be anything else) 636 for (; i < chars.length; i++) { 637 if ((chars[i] < '0' || chars[i] > '9') 638 && (chars[i] < 'a' || chars[i] > 'f') 639 && (chars[i] < 'A' || chars[i] > 'F')) { 640 return false; 641 } 642 } 643 return true; 644 } 645 } 646 sz--; // don't want to loop to the last char, check it afterwords 647 // for type qualifiers 648 int i = start; 649 // loop to the next to last char or to the last char if we need another digit to 650 // make a valid number (e.g. chars[0..5] = "1234E") 651 while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) { 652 if (chars[i] >= '0' && chars[i] <= '9') { 653 foundDigit = true; 654 allowSigns = false; 655 656 } else if (chars[i] == '.') { 657 if (hasDecPoint || hasExp) { 658 // two decimal points or dec in exponent 659 return false; 660 } 661 hasDecPoint = true; 662 } else if (chars[i] == 'e' || chars[i] == 'E') { 663 // we've already taken care of hex. 664 if (hasExp) { 665 // two E's 666 return false; 667 } 668 if (!foundDigit) { 669 return false; 670 } 671 hasExp = true; 672 allowSigns = true; 673 } else if (chars[i] == '+' || chars[i] == '-') { 674 if (!allowSigns) { 675 return false; 676 } 677 allowSigns = false; 678 foundDigit = false; // we need a digit after the E 679 } else { 680 return false; 681 } 682 i++; 683 } 684 if (i < chars.length) { 685 if (chars[i] >= '0' && chars[i] <= '9') { 686 // no type qualifier, OK 687 return true; 688 } 689 if (chars[i] == 'e' || chars[i] == 'E') { 690 // can't have an E at the last byte 691 return false; 692 } 693 if (!allowSigns 694 && (chars[i] == 'd' 695 || chars[i] == 'D' 696 || chars[i] == 'f' 697 || chars[i] == 'F')) { 698 return foundDigit; 699 } 700 if (chars[i] == 'l' 701 || chars[i] == 'L') { 702 // not allowing L with an exponent 703 return foundDigit && !hasExp; 704 } 705 // last character is illegal 706 return false; 707 } 708 // allowSigns is true iff the val ends in 'E' 709 // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass 710 return !allowSigns && foundDigit; 711 } 712 }