Best implementation for isNumber (string) method

In my limited experience, I worked on several projects that had some kind of class string class with methods to determine if a given string is a number. The idea was always the same, but the implementation was different. Some surround try parsing with try / catch

public boolean isInteger(String str) { try { Integer.parseInt(str); return true; } catch (NumberFormatException nfe) {} return false; } 

and others match regular expression

 public boolean isInteger(String str) { return str.matches("^-?[0-9]+(\\.[0-9]+)?$"); } 

Is one of these methods better than the other? I personally prefer to use the regex approach, as it is concise, but will it be executed by the parameter, if called, iterating over, say, a list of several hundred thousand lines?

Note. Since Iโ€™m new to the site, I donโ€™t quite understand this business community of the Wiki, so if this applies to it, let me know and I will gladly translate it.

EDIT: With all TryParse suggestions, I put the Asaph comparison code (thanks for a great post!) In C # and added the TryParse method. And, as it seems, TryParse wins hands. However, the try catch approach took an insane amount of time. As far as I think, I did something wrong! I also updated the regex to handle negative and decimal points.

Results for updated C # code:

 00:00:51.7390000 for isIntegerParseInt 00:00:03.9110000 for isIntegerRegex 00:00:00.3500000 for isIntegerTryParse 

Using:

 static bool isIntegerParseInt(string str) { try { int.Parse(str); return true; } catch (FormatException e){} return false; } static bool isIntegerRegex(string str) { return Regex.Match(str, "^-?[0-9]+(\\.[0-9]+)?$").Success; } static bool isIntegerTryParse(string str) { int bob; return Int32.TryParse(str, out bob); } 
+17
performance c #
Sep 02 '09 at 17:25
source share
19 answers

I just ran some performance tests of these two methods (on Macbook Pro OSX Leopard Java 6). ParseInt is faster. Here is the result:

 This operation took 1562 ms. This operation took 2251 ms. 

And here is my test code:

 public class IsIntegerPerformanceTest { public static boolean isIntegerParseInt(String str) { try { Integer.parseInt(str); return true; } catch (NumberFormatException nfe) {} return false; } public static boolean isIntegerRegex(String str) { return str.matches("^[0-9]+$"); } public static void main(String[] args) { long starttime, endtime; int iterations = 1000000; starttime = System.currentTimeMillis(); for (int i=0; i<iterations; i++) { isIntegerParseInt("123"); isIntegerParseInt("not an int"); isIntegerParseInt("-321"); } endtime = System.currentTimeMillis(); System.out.println("This operation took " + (endtime - starttime) + " ms."); starttime = System.currentTimeMillis(); for (int i=0; i<iterations; i++) { isIntegerRegex("123"); isIntegerRegex("not an int"); isIntegerRegex("-321"); } endtime = System.currentTimeMillis(); System.out.println("This operation took " + (endtime - starttime) + " ms."); } } 

Also note that your regular expression will reject negative numbers, and the parseInt method will accept them.

+13
Sep 02 '09 at 17:38
source share

Here is our way to do this:

 public boolean isNumeric(String string) throws IllegalArgumentException { boolean isnumeric = false; if (string != null && !string.equals("")) { isnumeric = true; char chars[] = string.toCharArray(); for(int d = 0; d < chars.length; d++) { isnumeric &= Character.isDigit(chars[d]); if(!isnumeric) break; } } return isnumeric; } 
+4
02 Sep '09 at 17:56
source share

If absolute performance is key, and if you just check for integers (not floating point numbers), I suspect that iterating over each character in the string, returning false if you encounter something outside the range of 0-9 will be fastest.

RegEx is a more versatile solution, so it probably wonโ€™t work so fast for this special case. In this case, the solution that throws the exception will have additional overhead. TryParse will be a little slower if you really don't care about the value of the number, just whether it is a number or not, since conversion to a number should also happen.

For anything other than the inner loop, which is called many times, the differences between all of these parameters should be minor.

+3
Sep 02 '09 at 17:30
source share

I needed to refactor code like yours to get rid of NumberFormatException. Reorganized Code:

 public static Integer parseInteger(final String str) { if (str == null || str.isEmpty()) { return null; } final Scanner sc = new Scanner(str); return Integer.valueOf(sc.nextInt()); } 

As a Java 1.4 guy, I did not know about java.util.Scanner . I found this interesting article:

http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Java

I liked the solution with the scanner, very compact and still readable.

+3
Feb 09 2018-12-12T00:
source share

Some languages, such as C #, have a TryParse (or equivalent) that works well enough for something like this.

 public boolean IsInteger(string value) { int i; return Int32.TryParse(value, i); } 
+2
Sep 02 '09 at 17:29
source share

Personally, I would do it if you really want to simplify it.

 public boolean isInteger(string myValue) { int myIntValue; return int.TryParse(myValue, myIntValue) } 
+2
Sep 02 '09 at 17:29
source share

You can create an extension method for the string and make the whole process cleaner ...

 public static bool IsInt(this string str) { int i; return int.TryParse(str, out i); } 

Then you can do the following in your actual code ...

 if(myString.IsInt()).... 
+2
Sep 02 '09 at 17:53
source share

Using .NET, you can do something like:

 private bool isNumber(string str) { return str.Any(c => !char.IsDigit(c)); } 
+1
Sep 02 '09 at 17:47
source share
 public static boolean CheckString(String myString) { char[] digits; digits = myString.toCharArray(); for (char div : digits) {// for each element div of type char in the digits collection (digits is a collection containing div elements). try { Double.parseDouble(myString); System.out.println("All are numbers"); return true; } catch (NumberFormatException e) { if (Character.isDigit(div)) { System.out.println("Not all are chars"); return false; } } } System.out.println("All are chars"); return true; } 
+1
Jan 27 '12 at 1:23
source share

This is my implementation to check if a string consists of numbers:

 public static boolean isNumeric(String string) { if (string == null) { throw new NullPointerException("The string must not be null!"); } final int len = string.length(); if (len == 0) { return false; } for (int i = 0; i < len; ++i) { if (!Character.isDigit(string.charAt(i))) { return false; } } return true; } 
+1
Mar 29 '13 at 23:48
source share

I like the code:

 public static boolean isIntegerRegex(String str) { return str.matches("^[0-9]+$"); } 

But when creating the template, it will be even more:

 public static Pattern patternInteger = Pattern.compile("^[0-9]+$"); public static boolean isIntegerRegex(String str) { return patternInteger.matcher(str).matches(); } 

To apply according to the test we have the result:

 This operation isIntegerParseInt took 1313 ms. This operation isIntegerRegex took 1178 ms. This operation isIntegerRegexNew took 304 ms. 

FROM

 public class IsIntegerPerformanceTest { private static Pattern pattern = Pattern.compile("^[0-9]+$"); public static boolean isIntegerParseInt(String str) { try { Integer.parseInt(str); return true; } catch (NumberFormatException nfe) { } return false; } public static boolean isIntegerRegexNew(String str) { return pattern.matcher(str).matches(); } public static boolean isIntegerRegex(String str) { return str.matches("^[0-9]+$"); } public static void main(String[] args) { long starttime, endtime; int iterations = 1000000; starttime = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { isIntegerParseInt("123"); isIntegerParseInt("not an int"); isIntegerParseInt("-321"); } endtime = System.currentTimeMillis(); System.out.println("This operation isIntegerParseInt took " + (endtime - starttime) + " ms."); starttime = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { isIntegerRegex("123"); isIntegerRegex("not an int"); isIntegerRegex("-321"); } endtime = System.currentTimeMillis(); System.out.println("This operation took isIntegerRegex " + (endtime - starttime) + " ms."); starttime = System.currentTimeMillis(); for (int i = 0; i < iterations; i++) { isIntegerRegexNew("123"); isIntegerRegexNew("not an int"); isIntegerRegexNew("-321"); } endtime = System.currentTimeMillis(); System.out.println("This operation took isIntegerRegexNew " + (endtime - starttime) + " ms."); } } 
+1
Aug 16 '13 at 4:12
source share

I think this could be faster than previous solutions if you do the following (Java):

 public final static boolean isInteger(String in) { char c; int length = in.length(); boolean ret = length > 0; int i = ret && in.charAt(0) == '-' ? 1 : 0; for (; ret && i < length; i++) { c = in.charAt(i); ret = (c >= '0' && c <= '9'); } return ret; } 

I ran the same code as Asaf, and the result:

This operation took 28 ms.

A huge difference (against 1691 ms and 2049 ms - on my computer). Note that this method does not check if the string is null, so you should do this earlier (including trimming the string)

+1
May 6 '14 at 19:52
source share

I think people here are missing a point. Using the same template repeatedly has very easy optimization. Just use a single template. In doing this, in all my tests, the try-catch approach never has a better guide than the template approach. With successful testing, try-catch takes twice as much time, and the failure test is 6 times slower.

 public static final Pattern INT_PATTERN= Pattern.compile("^-?[0-9]+(\\.[0-9]+)?$"); public static boolean isInt(String s){ return INT_PATTERN.matcher(s).matches(); } 
+1
Nov 15 '14 at 10:10
source share

I use it, but I liked the rigor of Asaf at his post.

 public static bool IsNumeric(object expression) { if (expression == null) return false; double number; return Double.TryParse(Convert.ToString(expression, CultureInfo.InvariantCulture), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out number); } 
0
02 Sep '09 at 17:45
source share

For long numbers use this: (JAVA)

 public static boolean isNumber(String string) { try { Long.parseLong(string); } catch (Exception e) { return false; } return true; } 
0
Feb 15 '13 at 16:26
source share
  public static boolean isNumber(String str){ return str.matches("[0-9]*\\.[0-9]+"); } 

to check if a number is (including float, integer) or not

0
Apr 18 '13 at 11:06 on
source share

A modified version of my previous answer:

 public static boolean isInteger(String in) { if (in != null) { char c; int i = 0; int l = in.length(); if (l > 0 && in.charAt(0) == '-') { i = 1; } if (l > i) { for (; i < l; i++) { c = in.charAt(i); if (c < '0' || c > '9') return false; } return true; } } return false; } 
0
May 09 '14 at 1:59
source share

I just added this class to my utilities:

 public class TryParseLong { private boolean isParseable; private long value; public TryParseLong(String toParse) { try { value = Long.parseLong(toParse); isParseable = true; } catch (NumberFormatException e) { // Exception set to null to indicate it is deliberately // being ignored, since the compensating action // of clearing the parsable flag is being taken. e = null; isParseable = false; } } public boolean isParsable() { return isParseable; } public long getLong() { return value; } } 

To use it:

 TryParseLong valueAsLong = new TryParseLong(value); if (valueAsLong.isParsable()) { ... // Do something with valueAsLong.getLong(); } else { ... } 

This only analyzes the value once.

It still uses exception and control flow with exceptions, but at least it encapsulates such code in a utility class, and the code it uses can work in a more ordinary way.

The problem with Java compared to C # is that C # matters and passes by reference, so it can effectively return 2 pieces of information; a flag indicating that something is being parsed or not, and the actual value being analyzed. When we reutrn> 1 value in Java, we need to create an object to store them, so I took this approach and put the flag and parsed value in the object.

Escape analysis is likely to handle this efficiently and create a value and flag on the stack and never create this object on the heap, so I think this will have minimal impact on performance.

In my opinion, this gives an optimal compromise between maintaining control over the flow of your code, good performance and not parsing an integer more than once.

0
Mar 03 '15 at 10:54
source share

public static boolean CheckIfNumber (line number) {

  for(int i = 0; i < number.length(); i++){ try{ Double.parseDouble(number.substring(i)); }catch(NumberFormatException ex){ return false; } } return true; } 

I had this problem before, but when I entered a number and then a character, it would still return true, I think this is the best way to do this. Just check if every char number is there. A little longer, but it takes care if you have a situation where the user enters "1abc". For some reason, when I tried to try to catch without iteration, he still believed that this number was so.

0
Apr 6 '16 at 0:26
source share



All Articles