C# isNumber(string) 方法的最佳实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1369077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:45:05  来源:igfitidea点击:

Best implementation for an isNumber(string) method

c#performance

提问by thorncp

In my limited experience, I've been on several projects that have had some sort of string utility class with methods to determine if a given string is a number. The idea has always been the same, however, the implementation has been different. Some surround a parse attempt with try/catch

以我有限的经验,我参与过几个项目,这些项目具有某种字符串实用程序类,其中包含确定给定字符串是否为数字的方法。想法一直是一样的,然而,实现却有所不同。有些用 try/catch 围绕解析尝试

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

and others match with regex

和其他匹配正则表达式

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

Is one of these methods better than the other? I personally prefer using the regex approach, as it's concise, but will it perform on par if called while iterating over, say, a list of a several hundred thousand strings?

这些方法中的一种比另一种更好吗?我个人更喜欢使用正则表达式方法,因为它很简洁,但是如果在迭代时调用它,比如几十万个字符串的列表,它的性能是否相同?

Note: As I'm kinda new to the site I don't fully understand this Community Wiki business, so if this belongs there let me know, and I'll gladly move it.

注意:由于我是该站点的新手,我并不完全了解此社区 Wiki 业务,所以如果它属于那里,请告诉我,我很乐意将其移动。

EDIT:With all the TryParse suggestions I ported Asaph's benchmark code (thanks for a great post!) to C# and added a TryParse method. And as it seems, the TryParse wins hands down. However, the try catch approach took a crazy amount of time. To the point of me thinking I did something wrong! I also updated regex to handle negatives and decimal points.

编辑:根据所有 TryParse 建议,我将 Asaph 的基准代码(感谢您的精彩帖子!)移植到 C# 并添加了一个 TryParse 方法。看起来,TryParse 赢得了胜利。然而,try catch 方法花费了大量的时间。以至于我觉得我做错了什么!我还更新了正则表达式来处理负数和小数点。

Results for updated, C# benchmark code:

更新的 C# 基准代码的结果:

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);
}

采纳答案by Asaph

I just ran some benchmarks on the performance of these 2 methods (On Macbook Pro OSX Leopard Java 6). ParseInt is faster. Here is the output:

我只是对这两种方法的性能进行了一些基准测试(在 Macbook Pro OSX Leopard Java 6 上)。ParseInt 更快。这是输出:

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

And here is my benchmark 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 regex will reject negative numbers and the parseInt method will accept them.

另请注意,您的正则表达式将拒绝负数,而 parseInt 方法将接受它们。

回答by Brandon

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

某些语言,如 C#,有一个 TryParse(或等效的),可以很好地处理这样的事情。

public boolean IsInteger(string value)
{
  int i;
  return Int32.TryParse(value, i);
}

回答by Mitchel Sellers

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

如果你真的想简化它,我个人会这样做。

public boolean isInteger(string myValue)
{
    int myIntValue;
    return int.TryParse(myValue, myIntValue)
}

回答by Eric J.

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

如果绝对性能是关键,并且如果您只是检查整数(而不是浮点数),我怀疑迭代字符串中的每个字符,如果遇到不在 0-9 范围内的内容,则返回 false 将是最快的。

RegEx is a more general-purpose solution so will probably not perform as fast for that special case. A solution that throws an exception will have some extra overhead in that case. TryParse will be slightlyslower if you don't actually care about the value of the number, just whether or not it is a number, since the conversion to a number must also take place.

RegEx 是一种更通用的解决方案,因此对于这种特殊情况可能不会执行得那么快。在这种情况下,抛出异常的解决方案会有一些额外的开销。如果您实际上并不关心数字的值,只关心它是否是数字,TryParse 会稍微慢一些,因为转换为数字也必须发生。

For anything but an inner loop that's called many times, the differences between all of these options should be insignificant.

除了多次调用的内部循环之外,所有这些选项之间的差异应该是微不足道的。

回答by Daver

I use this but I liked Asaph's rigor in his post.

我使用这个,但我喜欢 Asaph 在他的帖子中的严谨。

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);
}

回答by Cleiton

Using .NET, you could do something like:

使用 .NET,您可以执行以下操作:

private bool isNumber(string str)
{
    return str.Any(c => !char.IsDigit(c));
}

回答by RSolberg

You could create an extension method for a string, and make the whole process look cleaner...

您可以为字符串创建一个扩展方法,并使整个过程看起来更清晰......

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

You could then do the following in your actual code...

然后,您可以在实际代码中执行以下操作...

if(myString.IsInt())....

回答by Jeremy Cron

Here is our way of doing 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;
}

回答by Naim

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;
}

回答by Heiner

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

我需要重构像您这样的代码以摆脱 NumberFormatException。重构后的代码:

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 didn't know about java.util.Scanner. I found this interesting article:

作为一个 Java 1.4 的人,我不知道java.util.Scanner。我发现了这篇有趣的文章:

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

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

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

我个人喜欢带有扫描仪的解决方案,非常紧凑且仍然可读。