检查字符串是否仅包含数字的最快方法

Nah*_*hum 166 c#

我知道如何检查这个.正则表达式,int.parse,tryparse,循环.

谁能告诉我什么是最快的检查方式?

需要的是只需要CHECK就不需要实际解析.

这不是同一个问题:如何识别字符串是否为数字?

问题不仅仅在于识别方式.但是关于什么是最快的方法.

jak*_*sch 244

bool IsDigitsOnly(string str)
{
    foreach (char c in str)
    {
        if (c < '0' || c > '9')
            return false;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)

可能是最快的方法.

  • 如果有人关心,这当然可以简化为单线 - >`return str.All(c => c> ='0'&& c <='9'); (54认同)
  • @Keith`IsDigit`返回大约三百个字符的'true`.包括全宽十进制数字`0123` ...(在中国和日本很常见)和其他文化的数字,例如`01২1234꘤꘥꘦꘧꘨`等等. (27认同)
  • 你也可以这样做:`return str.All(char.IsDigit);`.万岁的方法组! (15认同)
  • 还有`char.IsDigit()` (14认同)
  • 请注意,空字符串不是虚拟号码. (11认同)
  • +1:IMO,这是检查字符串中是否只有C#中数字的最快方法 (2认同)
  • 点和逗号怎么样? (2认同)

The*_*ing 60

这是基于相同字符串的1000000个解析的一些基准测试:

更新了release统计信息:

IsDigitsOnly: 384588
TryParse:     639583
Regex:        1329571
Run Code Online (Sandbox Code Playgroud)

这是代码,看起来像IsDigitsOnly更快:

class Program
{
    private static Regex regex = new Regex("^[0-9]+$", RegexOptions.Compiled);

    static void Main(string[] args)
    {
        Stopwatch watch = new Stopwatch();
        string test = int.MaxValue.ToString();
        int value;

        watch.Start();
        for(int i=0; i< 1000000; i++)
        {
            int.TryParse(test, out value);
        }
        watch.Stop();
        Console.WriteLine("TryParse: "+watch.ElapsedTicks);

        watch.Reset();
        watch.Start();
        for (int i = 0; i < 1000000; i++)
        {
            IsDigitsOnly(test);
        }
        watch.Stop();
        Console.WriteLine("IsDigitsOnly: " + watch.ElapsedTicks);

        watch.Reset();
        watch.Start();
        for (int i = 0; i < 1000000; i++)
        {
            regex.IsMatch(test);
        }
        watch.Stop();
        Console.WriteLine("Regex: " + watch.ElapsedTicks);

        Console.ReadLine();
    }

    static bool IsDigitsOnly(string str)
    {
        foreach (char c in str)
        {
            if (c < '0' || c > '9')
                return false;
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然值得注意的是,TryParse确实允许前导/尾随空格以及特定于文化的符号.它的字符串长度也受到限制.

  • 哦,在编译时使用/ o +,它现在比int.TryParse快5倍.只是为了检查一下,你没有在调试器中运行,不是吗? (3认同)
  • 顺便说一句,对同一个字符串进行 1000 次解析几乎不需要任何时间,远低于自然噪声导致结果微不足道的时间。我预计必须解析它一百万次才能获得有用的计时。 (2认同)

Uda*_*day 48

您可以使用LINQ简单地执行此操作

return str.All(char.IsDigit);

  1. .All 对于空字符串返回true,对空字符串返回异常.
  2. char.IsDigit 适用于所有Unicode字符.

  • char.IsDigit匹配来自不同语言环境的大量unicode数字(请参阅http://www.fileformat.info/info/unicode/category/Nd/list.htm).此外,您的答案使用LINQ,因此它不太可能成为*最快*的方式.但对大多数用例来说可能就足够了. (2认同)

fla*_*ayn 34

char已经有一个IsDigit(char c),它执行此操作:

 public static bool IsDigit(char c)
    {
      if (!char.IsLatin1(c))
        return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;
      if ((int) c >= 48)
        return (int) c <= 57;
      else
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

var theString = "839278";
bool digitsOnly = theString.All(char.IsDigit);
Run Code Online (Sandbox Code Playgroud)

  • @ user823959:我不确定你的意思。Char.IsDigit 是 mscorelib 的一部分:http://msdn.microsoft.com/en-us/library/0t641e58.aspx (2认同)

Sla*_*lai 21

通过仅使用一次比较charfor不是foreach:而不是:

bool isDigits(string s) 
{ 
    if (s == null || s == "") return false; 

    for (int i = 0; i < s.Length; i++) 
        if ((s[i] ^ '0') > 9) 
            return false; 

    return true; 
}
Run Code Online (Sandbox Code Playgroud)

用于测试的代码(总是配置文件,因为结果取决于硬件,版本,订单等):

static bool isDigitsFr(string s) { if (s == null || s == "") return false; for (int i = 0; i < s.Length; i++) if (s[i] < '0' || s[i] > '9') return false; return true; }
static bool isDigitsFu(string s) { if (s == null || s == "") return false; for (int i = 0; i < s.Length; i++) if ((uint)(s[i] - '0') > 9) return false; return true; }
static bool isDigitsFx(string s) { if (s == null || s == "") return false; for (int i = 0; i < s.Length; i++) if ((s[i] ^ '0') > 9) return false; return true; }
static bool isDigitsEr(string s) { if (s == null || s == "") return false; foreach (char c in s) if (c < '0' || c > '9') return false; return true; }
static bool isDigitsEu(string s) { if (s == null || s == "") return false; foreach (char c in s) if ((uint)(c - '0') > 9) return false; return true; }
static bool isDigitsEx(string s) { if (s == null || s == "") return false; foreach (char c in s) if ((c ^ '0') > 9) return false; return true; }
static void test()
{
    var w = new Stopwatch(); bool b; var s = int.MaxValue + ""; int r = 12345678*2; var ss = new SortedSet<string>(); //s = string.Concat(Enumerable.Range(0, 127).Select(i => ((char)i ^ '0') < 10 ? 1 : 0));
    w.Restart(); for (int i = 0; i < r; i++) b = s.All(char.IsDigit); w.Stop(); ss.Add(w.Elapsed + ".All .IsDigit"); 
    w.Restart(); for (int i = 0; i < r; i++) b = s.All(c => c >= '0' && c <= '9'); w.Stop(); ss.Add(w.Elapsed + ".All <>"); 
    w.Restart(); for (int i = 0; i < r; i++) b = s.All(c => (c ^ '0') < 10); w.Stop(); ss.Add(w.Elapsed + " .All ^"); 
    w.Restart(); for (int i = 0; i < r; i++) b = isDigitsFr(s); w.Stop(); ss.Add(w.Elapsed + " for     <>");
    w.Restart(); for (int i = 0; i < r; i++) b = isDigitsFu(s); w.Stop(); ss.Add(w.Elapsed + " for     -");
    w.Restart(); for (int i = 0; i < r; i++) b = isDigitsFx(s); w.Stop(); ss.Add(w.Elapsed + " for     ^");
    w.Restart(); for (int i = 0; i < r; i++) b = isDigitsEr(s); w.Stop(); ss.Add(w.Elapsed + " foreach <>");
    w.Restart(); for (int i = 0; i < r; i++) b = isDigitsEu(s); w.Stop(); ss.Add(w.Elapsed + " foreach -");
    w.Restart(); for (int i = 0; i < r; i++) b = isDigitsEx(s); w.Stop(); ss.Add(w.Elapsed + " foreach ^");
    MessageBox.Show(string.Join("\n", ss)); return;
}
Run Code Online (Sandbox Code Playgroud)

英特尔i5-3470 @ 3.2GHz,VS 2015 .NET 4.6.1发布模式和优化启用的结果:

time    method          ratio
0.7776  for     ^       1.0000 
0.7984  foreach -       1.0268 
0.8066  foreach ^       1.0372 
0.8940  for     -       1.1497 
0.8976  for     <>      1.1543 
0.9456  foreach <>      1.2160 
4.4559  .All <>         5.7303 
4.7791  .All ^          6.1458 
4.8539  .All. IsDigit   6.2421 
Run Code Online (Sandbox Code Playgroud)

对于任何想要使用较短方法的人,请注意


Bra*_*vic 13

如果你担心性能,既不使用int.TryParse也不使用Regex- 编写自己的(简单)函数(DigitsOnly或者 DigitsOnly2在下面,但不是 DigitsOnly3 - LINQ似乎会产生很大的开销).

另外,请注意,int.TryParse如果字符串太长而无法"适应" ,则会失败int.

这个简单的基准......

class Program {

    static bool DigitsOnly(string s) {
        int len = s.Length;
        for (int i = 0; i < len; ++i) {
            char c = s[i];
            if (c < '0' || c > '9')
                return false;
        }
        return true;
    }

    static bool DigitsOnly2(string s) {
        foreach (char c in s) {
            if (c < '0' || c > '9')
                return false;
        }
        return true;
    }

    static bool DigitsOnly3(string s) {
        return s.All(c => c >= '0' && c <= '9');
    }

    static void Main(string[] args) {

        const string s1 = "916734184";
        const string s2 = "916734a84";

        const int iterations = 1000000;
        var sw = new Stopwatch();

        sw.Restart();
        for (int i = 0 ; i < iterations; ++i) {
            bool success = DigitsOnly(s1);
            bool failure = DigitsOnly(s2);
        }
        sw.Stop();
        Console.WriteLine(string.Format("DigitsOnly: {0}", sw.Elapsed));

        sw.Restart();
        for (int i = 0; i < iterations; ++i) {
            bool success = DigitsOnly2(s1);
            bool failure = DigitsOnly2(s2);
        }
        sw.Stop();
        Console.WriteLine(string.Format("DigitsOnly2: {0}", sw.Elapsed));

        sw.Restart();
        for (int i = 0; i < iterations; ++i) {
            bool success = DigitsOnly3(s1);
            bool failure = DigitsOnly3(s2);
        }
        sw.Stop();
        Console.WriteLine(string.Format("DigitsOnly3: {0}", sw.Elapsed));

        sw.Restart();
        for (int i = 0; i < iterations; ++i) {
            int dummy;
            bool success = int.TryParse(s1, out dummy);
            bool failure = int.TryParse(s2, out dummy);
        }
        sw.Stop();
        Console.WriteLine(string.Format("int.TryParse: {0}", sw.Elapsed));

        sw.Restart();
        var regex = new Regex("^[0-9]+$", RegexOptions.Compiled);
        for (int i = 0; i < iterations; ++i) {
            bool success = regex.IsMatch(s1);
            bool failure = regex.IsMatch(s2);
        }
        sw.Stop();
        Console.WriteLine(string.Format("Regex.IsMatch: {0}", sw.Elapsed));

    }

}
Run Code Online (Sandbox Code Playgroud)

...产生以下结果......

DigitsOnly: 00:00:00.0346094
DigitsOnly2: 00:00:00.0365220
DigitsOnly3: 00:00:00.2669425
int.TryParse: 00:00:00.3405548
Regex.IsMatch: 00:00:00.7017648
Run Code Online (Sandbox Code Playgroud)


小智 10

我喜欢Linq并且在第一次不匹配时让它退出你可以做到这一点

string str = '0129834X33';
bool isAllDigits = !str.Any( ch=> ch < '0' || ch > '9' );
Run Code Online (Sandbox Code Playgroud)


Pet*_*nov 8

这应该工作:

Regex.IsMatch("124", "^[0-9]+$", RegexOptions.Compiled)
Run Code Online (Sandbox Code Playgroud)

int.Parse或者int.TryParse不会一直有效,因为字符串可能包含int可以容纳的更多数字.

如果你要多次检查它,那么使用编译的正则表达式是有用的 - 第一次需要更多时间,但之后要快得多.

  • 这是错误的,如果甚至是一位数,它返回true.虽然遵守的想法很棒. (3认同)

Atu*_*lya 7

可能最快的方法是:

myString.All(c => char.IsDigit(c))
Run Code Online (Sandbox Code Playgroud)

注意:如果你的字符串为空,这将返回True,这是不正确的(如果你不认为空为有效数字/数字)


Ste*_*olt 5

您可以在一行LINQ语句中执行此操作.好吧,我意识到这不一定是最快的,所以从技术上来说不能回答这个问题,但它可能是最容易编写的:

str.All(c => c >= '0' && c <= '9')
Run Code Online (Sandbox Code Playgroud)

  • `str.All(char.IsDigit)`更容易编写,但当然不等同于你的代码. (4认同)

use*_*351 5

这可能会来得超级晚!但我相信它会帮助某人,因为它帮助了我。

        private static bool IsDigitsOnly(string str)
        {
            return str.All(c => c >= '0' && c <= '9');
        }
Run Code Online (Sandbox Code Playgroud)


i31*_*nGo 5

空验证功能:

public static bool IsDigitsOnly(string str)
  {             
        return !string.IsNullOrEmpty(str) && str.All(char.IsDigit);
  }
Run Code Online (Sandbox Code Playgroud)


小智 5

如果是单个字符串:

if (str.All(Char.IsDigit))
{
  // string contains only digits
}
Run Code Online (Sandbox Code Playgroud)

如果它是一个字符串列表:

if (lstStr.All(s => s.All(Char.IsDigit)))
{
  // List of strings contains only digits
}
Run Code Online (Sandbox Code Playgroud)