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 Apache Software Foundation 026 * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a> 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 905636 2010-02-02 14:03:32Z niallp $ 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.length() == 1 && !Character.isDigit(val.charAt(0))) { 146 throw new NumberFormatException(val + " is not a valid number."); 147 } 148 if (val.startsWith("--")) { 149 // this is protection for poorness in java.lang.BigDecimal. 150 // it accepts this as a legal value, but it does not appear 151 // to be in specification of class. OS X Java parses it to 152 // a wrong value. 153 return null; 154 } 155 if (val.startsWith("0x") || val.startsWith("-0x")) { 156 return createInteger(val); 157 } 158 char lastChar = val.charAt(val.length() - 1); 159 String mant; 160 String dec; 161 String exp; 162 int decPos = val.indexOf('.'); 163 int expPos = val.indexOf('e') + val.indexOf('E') + 1; 164 165 if (decPos > -1) { 166 167 if (expPos > -1) { 168 if (expPos < decPos) { 169 throw new NumberFormatException(val + " is not a valid number."); 170 } 171 dec = val.substring(decPos + 1, expPos); 172 } else { 173 dec = val.substring(decPos + 1); 174 } 175 mant = val.substring(0, decPos); 176 } else { 177 if (expPos > -1) { 178 mant = val.substring(0, expPos); 179 } else { 180 mant = val; 181 } 182 dec = null; 183 } 184 if (!Character.isDigit(lastChar)) { 185 if (expPos > -1 && expPos < val.length() - 1) { 186 exp = val.substring(expPos + 1, val.length() - 1); 187 } else { 188 exp = null; 189 } 190 //Requesting a specific type.. 191 String numeric = val.substring(0, val.length() - 1); 192 boolean allZeros = isAllZeros(mant) && isAllZeros(exp); 193 switch (lastChar) { 194 case 'l' : 195 case 'L' : 196 if (dec == null 197 && exp == null 198 && (numeric.charAt(0) == '-' && isDigits(numeric.substring(1)) || isDigits(numeric))) { 199 try { 200 return createLong(numeric); 201 } catch (NumberFormatException nfe) { 202 //Too big for a long 203 } 204 return createBigInteger(numeric); 205 206 } 207 throw new NumberFormatException(val + " is not a valid number."); 208 case 'f' : 209 case 'F' : 210 try { 211 Float f = NumberUtils.createFloat(numeric); 212 if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) { 213 //If it's too big for a float or the float value = 0 and the string 214 //has non-zeros in it, then float does not have the precision we want 215 return f; 216 } 217 218 } catch (NumberFormatException e) { 219 // ignore the bad number 220 } 221 //$FALL-THROUGH$ 222 case 'd' : 223 case 'D' : 224 try { 225 Double d = NumberUtils.createDouble(numeric); 226 if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) { 227 return d; 228 } 229 } catch (NumberFormatException nfe) { 230 // empty catch 231 } 232 try { 233 return createBigDecimal(numeric); 234 } catch (NumberFormatException e) { 235 // empty catch 236 } 237 //$FALL-THROUGH$ 238 default : 239 throw new NumberFormatException(val + " is not a valid number."); 240 241 } 242 } else { 243 //User doesn't have a preference on the return type, so let's start 244 //small and go from there... 245 if (expPos > -1 && expPos < val.length() - 1) { 246 exp = val.substring(expPos + 1, val.length()); 247 } else { 248 exp = null; 249 } 250 if (dec == null && exp == null) { 251 //Must be an int,long,bigint 252 try { 253 return createInteger(val); 254 } catch (NumberFormatException nfe) { 255 // empty catch 256 } 257 try { 258 return createLong(val); 259 } catch (NumberFormatException nfe) { 260 // empty catch 261 } 262 return createBigInteger(val); 263 264 } else { 265 //Must be a float,double,BigDec 266 boolean allZeros = isAllZeros(mant) && isAllZeros(exp); 267 try { 268 Float f = createFloat(val); 269 if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) { 270 return f; 271 } 272 } catch (NumberFormatException nfe) { 273 // empty catch 274 } 275 try { 276 Double d = createDouble(val); 277 if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) { 278 return d; 279 } 280 } catch (NumberFormatException nfe) { 281 // empty catch 282 } 283 284 return createBigDecimal(val); 285 286 } 287 288 } 289 } 290 291 /** 292 * <p>Utility method for {@link #createNumber(java.lang.String)}.</p> 293 * 294 * <p>Returns <code>true</code> if s is <code>null</code>.</p> 295 * 296 * @param s the String to check 297 * @return if it is all zeros or <code>null</code> 298 */ 299 private static boolean isAllZeros(String s) { 300 if (s == null) { 301 return true; 302 } 303 for (int i = s.length() - 1; i >= 0; i--) { 304 if (s.charAt(i) != '0') { 305 return false; 306 } 307 } 308 return s.length() > 0; 309 } 310 311 //-------------------------------------------------------------------- 312 313 /** 314 * <p>Convert a <code>String</code> to a <code>Float</code>.</p> 315 * 316 * @param val a <code>String</code> to convert 317 * @return converted <code>Float</code> 318 * @throws NumberFormatException if the value cannot be converted 319 */ 320 public static Float createFloat(String val) { 321 return Float.valueOf(val); 322 } 323 324 /** 325 * <p>Convert a <code>String</code> to a <code>Double</code>.</p> 326 * 327 * @param val a <code>String</code> to convert 328 * @return converted <code>Double</code> 329 * @throws NumberFormatException if the value cannot be converted 330 */ 331 public static Double createDouble(String val) { 332 return Double.valueOf(val); 333 } 334 335 /** 336 * <p>Convert a <code>String</code> to a <code>Integer</code>, handling 337 * hex and octal notations.</p> 338 * 339 * @param val a <code>String</code> to convert 340 * @return converted <code>Integer</code> 341 * @throws NumberFormatException if the value cannot be converted 342 */ 343 public static Integer createInteger(String val) { 344 // decode() handles 0xAABD and 0777 (hex and octal) as well. 345 return Integer.decode(val); 346 } 347 348 /** 349 * <p>Convert a <code>String</code> to a <code>Long</code>.</p> 350 * 351 * @param val a <code>String</code> to convert 352 * @return converted <code>Long</code> 353 * @throws NumberFormatException if the value cannot be converted 354 */ 355 public static Long createLong(String val) { 356 return Long.valueOf(val); 357 } 358 359 /** 360 * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p> 361 * 362 * @param val a <code>String</code> to convert 363 * @return converted <code>BigInteger</code> 364 * @throws NumberFormatException if the value cannot be converted 365 */ 366 public static BigInteger createBigInteger(String val) { 367 BigInteger bi = new BigInteger(val); 368 return bi; 369 } 370 371 /** 372 * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p> 373 * 374 * @param val a <code>String</code> to convert 375 * @return converted <code>BigDecimal</code> 376 * @throws NumberFormatException if the value cannot be converted 377 */ 378 public static BigDecimal createBigDecimal(String val) { 379 BigDecimal bd = new BigDecimal(val); 380 return bd; 381 } 382 383 //-------------------------------------------------------------------- 384 385 /** 386 * <p>Gets the minimum of three <code>long</code> values.</p> 387 * 388 * @param a value 1 389 * @param b value 2 390 * @param c value 3 391 * @return the smallest of the values 392 */ 393 public static long minimum(long a, long b, long c) { 394 if (b < a) { 395 a = b; 396 } 397 if (c < a) { 398 a = c; 399 } 400 return a; 401 } 402 403 /** 404 * <p>Gets the minimum of three <code>int</code> values.</p> 405 * 406 * @param a value 1 407 * @param b value 2 408 * @param c value 3 409 * @return the smallest of the values 410 */ 411 public static int minimum(int a, int b, int c) { 412 if (b < a) { 413 a = b; 414 } 415 if (c < a) { 416 a = c; 417 } 418 return a; 419 } 420 421 /** 422 * <p>Gets the maximum of three <code>long</code> values.</p> 423 * 424 * @param a value 1 425 * @param b value 2 426 * @param c value 3 427 * @return the largest of the values 428 */ 429 public static long maximum(long a, long b, long c) { 430 if (b > a) { 431 a = b; 432 } 433 if (c > a) { 434 a = c; 435 } 436 return a; 437 } 438 439 /** 440 * <p>Gets the maximum of three <code>int</code> values.</p> 441 * 442 * @param a value 1 443 * @param b value 2 444 * @param c value 3 445 * @return the largest of the values 446 */ 447 public static int maximum(int a, int b, int c) { 448 if (b > a) { 449 a = b; 450 } 451 if (c > a) { 452 a = c; 453 } 454 return a; 455 } 456 457 //-------------------------------------------------------------------- 458 459 /** 460 * <p>Compares two <code>doubles</code> for order.</p> 461 * 462 * <p>This method is more comprehensive than the standard Java greater 463 * than, less than and equals operators.</p> 464 * <ul> 465 * <li>It returns <code>-1</code> if the first value is less than the second. 466 * <li>It returns <code>+1</code> if the first value is greater than the second. 467 * <li>It returns <code>0</code> if the values are equal. 468 * </ul> 469 * 470 * <p> 471 * The ordering is as follows, largest to smallest: 472 * <ul> 473 * <li>NaN 474 * <li>Positive infinity 475 * <li>Maximum double 476 * <li>Normal positive numbers 477 * <li>+0.0 478 * <li>-0.0 479 * <li>Normal negative numbers 480 * <li>Minimum double (-Double.MAX_VALUE) 481 * <li>Negative infinity 482 * </ul> 483 * </p> 484 * 485 * <p>Comparing <code>NaN</code> with <code>NaN</code> will 486 * return <code>0</code>.</p> 487 * 488 * @param lhs the first <code>double</code> 489 * @param rhs the second <code>double</code> 490 * @return <code>-1</code> if lhs is less, <code>+1</code> if greater, 491 * <code>0</code> if equal to rhs 492 */ 493 public static int compare(double lhs, double rhs) { 494 if (lhs < rhs) { 495 return -1; 496 } 497 if (lhs > rhs) { 498 return +1; 499 } 500 // Need to compare bits to handle 0.0 == -0.0 being true 501 // compare should put -0.0 < +0.0 502 // Two NaNs are also == for compare purposes 503 // where NaN == NaN is false 504 long lhsBits = Double.doubleToLongBits(lhs); 505 long rhsBits = Double.doubleToLongBits(rhs); 506 if (lhsBits == rhsBits) { 507 return 0; 508 } 509 // Something exotic! A comparison to NaN or 0.0 vs -0.0 510 // Fortunately NaN's long is > than everything else 511 // Also negzeros bits < poszero 512 // NAN: 9221120237041090560 513 // MAX: 9218868437227405311 514 // NEGZERO: -9223372036854775808 515 if (lhsBits < rhsBits) { 516 return -1; 517 } else { 518 return +1; 519 } 520 } 521 522 /** 523 * <p>Compares two floats for order.</p> 524 * 525 * <p>This method is more comprehensive than the standard Java greater than, 526 * less than and equals operators.</p> 527 * <ul> 528 * <li>It returns <code>-1</code> if the first value is less than the second. 529 * <li>It returns <code>+1</code> if the first value is greater than the second. 530 * <li>It returns <code>0</code> if the values are equal. 531 * </ul> 532 * 533 * <p> The ordering is as follows, largest to smallest: 534 * <ul> 535 * <li>NaN 536 * <li>Positive infinity 537 * <li>Maximum float 538 * <li>Normal positive numbers 539 * <li>+0.0 540 * <li>-0.0 541 * <li>Normal negative numbers 542 * <li>Minimum float (-Float.MAX_VALUE) 543 * <li>Negative infinity 544 * </ul> 545 * 546 * <p>Comparing <code>NaN</code> with <code>NaN</code> will return 547 * <code>0</code>.</p> 548 * 549 * @param lhs the first <code>float</code> 550 * @param rhs the second <code>float</code> 551 * @return <code>-1</code> if lhs is less, <code>+1</code> if greater, 552 * <code>0</code> if equal to rhs 553 */ 554 public static int compare(float lhs, float rhs) { 555 if (lhs < rhs) { 556 return -1; 557 } 558 if (lhs > rhs) { 559 return +1; 560 } 561 //Need to compare bits to handle 0.0 == -0.0 being true 562 // compare should put -0.0 < +0.0 563 // Two NaNs are also == for compare purposes 564 // where NaN == NaN is false 565 int lhsBits = Float.floatToIntBits(lhs); 566 int rhsBits = Float.floatToIntBits(rhs); 567 if (lhsBits == rhsBits) { 568 return 0; 569 } 570 //Something exotic! A comparison to NaN or 0.0 vs -0.0 571 //Fortunately NaN's int is > than everything else 572 //Also negzeros bits < poszero 573 //NAN: 2143289344 574 //MAX: 2139095039 575 //NEGZERO: -2147483648 576 if (lhsBits < rhsBits) { 577 return -1; 578 } else { 579 return +1; 580 } 581 } 582 583 //-------------------------------------------------------------------- 584 585 /** 586 * <p>Checks whether the <code>String</code> contains only 587 * digit characters.</p> 588 * 589 * <p><code>Null</code> and empty String will return 590 * <code>false</code>.</p> 591 * 592 * @param str the <code>String</code> to check 593 * @return <code>true</code> if str contains only unicode numeric 594 */ 595 public static boolean isDigits(String str) { 596 if ((str == null) || (str.length() == 0)) { 597 return false; 598 } 599 for (int i = 0; i < str.length(); i++) { 600 if (!Character.isDigit(str.charAt(i))) { 601 return false; 602 } 603 } 604 return true; 605 } 606 607 /** 608 * <p>Checks whether the String a valid Java number.</p> 609 * 610 * <p>Valid numbers include hexadecimal marked with the <code>0x</code> 611 * qualifier, scientific notation and numbers marked with a type 612 * qualifier (e.g. 123L).</p> 613 * 614 * <p><code>Null</code> and empty String will return 615 * <code>false</code>.</p> 616 * 617 * @param str the <code>String</code> to check 618 * @return <code>true</code> if the string is a correctly formatted number 619 */ 620 public static boolean isNumber(String str) { 621 if (StringUtils.isEmpty(str)) { 622 return false; 623 } 624 char[] chars = str.toCharArray(); 625 int sz = chars.length; 626 boolean hasExp = false; 627 boolean hasDecPoint = false; 628 boolean allowSigns = false; 629 boolean foundDigit = false; 630 // deal with any possible sign up front 631 int start = (chars[0] == '-') ? 1 : 0; 632 if (sz > start + 1) { 633 if (chars[start] == '0' && chars[start + 1] == 'x') { 634 int i = start + 2; 635 if (i == sz) { 636 return false; // str == "0x" 637 } 638 // checking hex (it can't be anything else) 639 for (; i < chars.length; i++) { 640 if ((chars[i] < '0' || chars[i] > '9') 641 && (chars[i] < 'a' || chars[i] > 'f') 642 && (chars[i] < 'A' || chars[i] > 'F')) { 643 return false; 644 } 645 } 646 return true; 647 } 648 } 649 sz--; // don't want to loop to the last char, check it afterwords 650 // for type qualifiers 651 int i = start; 652 // loop to the next to last char or to the last char if we need another digit to 653 // make a valid number (e.g. chars[0..5] = "1234E") 654 while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) { 655 if (chars[i] >= '0' && chars[i] <= '9') { 656 foundDigit = true; 657 allowSigns = false; 658 659 } else if (chars[i] == '.') { 660 if (hasDecPoint || hasExp) { 661 // two decimal points or dec in exponent 662 return false; 663 } 664 hasDecPoint = true; 665 } else if (chars[i] == 'e' || chars[i] == 'E') { 666 // we've already taken care of hex. 667 if (hasExp) { 668 // two E's 669 return false; 670 } 671 if (!foundDigit) { 672 return false; 673 } 674 hasExp = true; 675 allowSigns = true; 676 } else if (chars[i] == '+' || chars[i] == '-') { 677 if (!allowSigns) { 678 return false; 679 } 680 allowSigns = false; 681 foundDigit = false; // we need a digit after the E 682 } else { 683 return false; 684 } 685 i++; 686 } 687 if (i < chars.length) { 688 if (chars[i] >= '0' && chars[i] <= '9') { 689 // no type qualifier, OK 690 return true; 691 } 692 if (chars[i] == 'e' || chars[i] == 'E') { 693 // can't have an E at the last byte 694 return false; 695 } 696 if (!allowSigns 697 && (chars[i] == 'd' 698 || chars[i] == 'D' 699 || chars[i] == 'f' 700 || chars[i] == 'F')) { 701 return foundDigit; 702 } 703 if (chars[i] == 'l' 704 || chars[i] == 'L') { 705 // not allowing L with an exponent 706 return foundDigit && !hasExp; 707 } 708 // last character is illegal 709 return false; 710 } 711 // allowSigns is true iff the val ends in 'E' 712 // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass 713 return !allowSigns && foundDigit; 714 } 715 }