tags:

views:

1804

answers:

5

How would you check if a string was a number before parsing it?

+1  A: 

Parse it (i.e. with http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Integer.html#parseInt(java.lang.String) ) and simply catch the exception =)

To clarify: The parseInt function checks if it can parse the number in any case (obviously) and if you want to parse it anyway, you are not going to take any performance hit by actually doing the parsing.

If you would not want to parse it (or parse it very, very rarely) you might wish to do it differently of course.

dionadar
A: 

You can use:

 try
 {
      NubmerFormat.parse( str);
 }
 catch(ParseException e)
 {
     //Not a number.
 }
Artem Barger
A: 

I think the only way to reliably tell if a string is a number, is to parse it. So I would just parse it, and if it's a number, you get the number in an int for free!

jqno
+13  A: 

This is generally done with a simple user-defined function (i.e. Roll-your-own "isNumeric" function).

Something like:

public static boolean isNumeric(String str)  
{  
  try  
  {  
    double d = Double.parseDouble(str);  
  }  
  catch(NumberFormatException nfe)  
  {  
    return false;  
  }  
  return true;  
}

However, if you're calling this function a lot, and you expect many of the checks to fail due to not being a number then performance of this mechanism will not be great, since you're relying upon exceptions being thrown for each failure, which is a fairly expensive operation.

An alternative approach may be to use a regular expression to check for validity of being a number:

public static boolean isNumeric(String str)
{
  return str.matches("-?\\d+(.\\d+)?");
}

Be careful with the above RegEx mechanism, though, as it'll fail if your using non-latin (i.e. 0 to 9) digits. For example, arabic digits. This is because the "\d" part of the RegEx will only match [0-9] and effectively isn't internationally numerically aware. (Thanks to OregonGhost for pointing this out!)

Or even another alternative is to use Java's built-in java.text.NumberFormat object to see if, after parsing the string the parser position is at the end of the string. If it is, we can assume the entire string is numeric:

public static boolean isNumeric(String str)
{
  NumberFormat formatter = NumberFormat.getInstance();
  ParsePosition pos = new ParsePosition(0);
  formatter.parse(str, pos);
  return str.length() == pos.getIndex();
}
CraigTP
Does \d in Java Regex match only latin digits? If it's like .NET regexes, you'll run into a problem with other (e.g. arabic) digits, as explained here: http://blogs.msdn.com/oldnewthing/archive/2004/03/09/86555.aspx
OregonGhost
@OregonGhost - Oops.. Good catch. You're right. \d will only match latin digits (i.e. 0 through to 9 effectively) and fail with arabic ones. I've edited my posted to make this clear. Thanks!
CraigTP
the numberFormatter solution is probably only marginally better than catching the NumberFormatException one. I suspect the best way is to use regex one.
Chii
Note that the `.` in your regex will match any character, not just the decimal separator character.
jqno
A: 

That's why I like the Try* approach in .NET. In addition to the traditional Parse method that's like the Java one, you also have a TryParse method. I'm not good in Java syntax (out parameters?), so please treat the following as some kind of pseudo-code. It should make the concept clear though.

boolean TryParseInt(String s, out int number)
{
    try {
        number = Integer.parseInt(myString);
        return true;
    } catch(NumberFormatException e) {
        return false;
    }
}

Usage:

int num;
if (TryParseInt("23", out num)) {
    // Do something with num.
}
OregonGhost
yep, there's no "out parameters" in Java and since the Integer wrapper is immutable (thus cannot be used as a valid reference to store the output), the sensible idiomatic option would be to return an Integer object that could be null if the parse failed. An uglier option could be to pass an int[1] as output parameter.
fortran
Yes, I remember a discussion about why Java has no output parameters. but returning an Integer (as null, if needed) would be fine too, I guess, though I don't know about Java's performance with regard to boxing/unboxing.
OregonGhost