c#中检查字符串是否只包含数字的最快方法

本文关键字:数字 方法 包含 检查 字符串 是否 | 更新日期: 2023-09-27 18:08:50

我知道几种检查字符串是否只包含数字的方法:
RegEx, int.parse, tryparse,循环等

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

我只需要检查的值,不需要实际解析它。

,"digit"我指的是ASCII数字:0 1 2 3 4 5 6 7 8 9

这与识别字符串是否为数字不同,因为这个问题不仅是关于如何识别,而且是关于最快的方法是什么。

c#中检查字符串是否只包含数字的最快方法

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

可能是最快的方法。

您可以简单地使用LINQ:

return str.All(char.IsDigit);

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

下面是基于同一字符串的1000000次解析的一些基准测试:

release数据更新:

IsDigitsOnly: 384588
TryParse:     639583
Regex:        1329571
下面是代码,看起来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;
    }
}

当然值得注意的是,TryParse允许前后空白以及特定文化的符号。它还限制字符串的长度

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

你可以简单地这样做:

var theString = "839278";
bool digitsOnly = theString.All(char.IsDigit);

通过对charfor而不是foreach只使用一次比较,可以提高约20%的速度:

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

用于测试的代码(总是概要文件,因为结果取决于硬件、版本、顺序等):

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

在Intel 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 

对于想要使用更短的方法的人,请注意

  • .All导致true为空字符串,null字符串异常
  • char.IsDigit对于Nd类别中的所有Unicode字符为真
  • int.TryParse还允许空格和符号字符

如果您关心性能,请不要使用int.TryParseRegex -编写您自己的(简单)函数(DigitsOnlyDigitsOnly2下面,但不是 DigitsOnly3 - LINQ似乎会产生显着的开销)。

另外,要注意,如果字符串太长而不能"适合"int,则int.TryParse将失败。

这个简单的基准…

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

…生成以下结果…

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

空验证函数:

public static bool IsDigitsOnly(string str)
  {             
        return !string.IsNullOrEmpty(str) && str.All(char.IsDigit);
  }

我喜欢Linq,如果想让它在第一次不匹配时退出,可以这样做

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

如果是单个字符串:

if (str.All(Char.IsDigit))
{
  // string contains only digits
}

如果是字符串列表:

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

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

str.All(c => c >= '0' && c <= '9')

最快的方法可能是:

myString.All(c => char.IsDigit(c))

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

应该可以:

Regex.IsMatch("124", "^[0-9]+$", RegexOptions.Compiled)

int.Parseint.TryParse并不总是有效,因为字符串可能包含int型可容纳的更多数字。

如果您要多次执行此检查,则使用编译后的regex是有用的-第一次需要更多时间,但之后要快得多。

这可能来得太晚了!,但我相信它会帮助别人,就像它帮助过我一样。

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

您可以尝试使用正则表达式,通过使用c#中的.IsMatch(string input, string pattern)方法测试输入字符串是否只有数字(0-9)。

using System;
using System.Text.RegularExpression;
public namespace MyNS
{
    public class MyClass
    {
        public void static Main(string[] args)
        {
             string input = Console.ReadLine();
             bool containsNumber = ContainsOnlyDigits(input);
        }
        private bool ContainOnlyDigits (string input)
        {
            bool containsNumbers = true;
            if (!Regex.IsMatch(input, @"/d"))
            {
                containsNumbers = false;
            }
            return containsNumbers;
        }
    }
}

这会很好地工作,还有许多其他方法,但这将工作

bool IsDigitsOnly(string str)
    {
        if (str.Length > 0)//if contains characters
        {
            foreach (char c in str)//assign character to c
            {
                if (c < '0' || c > '9')//check if its outside digit range
                    return false;
            }
        }else//empty string
        {
            return false;//empty string 
        }
        return true;//only digits
    }

另一种方法!

string str = "12345";
bool containsOnlyDigits = true;
try { if(Convert.ToInt32(str) < 0){ containsOnlyDigits = false; } }
catch { containsOnlyDigits = false; }

这里,如果语句Convert.ToInt32(str)失败,则string不包含数字。另一种可能性是,如果字符串的"-12345"被成功转换为-12345,那么有一个检查来验证转换的数字不小于零。

我做了一些小改动@ theecodeking的答案

似乎;

对于int类型最快的方法是TryParse

对于长类型最快的方式是Regex。

我的结果如下(勾号)

For int:
TryParse Max: 355788
IsDigitsOnly Max: 787013
Regex Max: 1297691
TryParse Avg: 186007
IsDigitsOnly Avg: 430963
Regex Avg: 464657,79
TryParse Min: 162742
IsDigitsOnly Min: 335646
Regex Min: 452121

For float :
TryParse Max : 3151995
IsDigitsOnly Max: 1392740
Regex Max : 1283451
TryParse Avg: 1391636
IsDigitsOnly Avg: 824029
Regex Avg: 501176
TryParse Min: 1187410
IsDigitsOnly Min: 706646
Regex Min: 476204

代码:

using System.Diagnostics;
using System.Text.RegularExpressions;
class Program
{
    private static Regex regex = new Regex("^[0-9]+$", RegexOptions.Compiled);
    static void Main(string[] args)
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        watch.Stop();
        watch.Reset();
        List<TimeSpan> tryparse = new List<TimeSpan>();
        List<TimeSpan> isdigitsonly = new List<TimeSpan>();
        List<TimeSpan> regexss = new List<TimeSpan>();
        for (int say = 0; say < 1000; say++)
        { 
            float value;
            string test = Random.Shared.NextInt64(1000,long.MaxValue).ToString();
            watch.Start();
            for (int i = 0; i < 1000000; i++)
            {
                float.TryParse(test, out value);
            }
            watch.Stop();
            //Console.WriteLine("TryParse: " + watch.Elapsed);
            tryparse.Add(watch.Elapsed);
            watch.Reset();
            watch.Start();
            for (int i = 0; i < 1000000; i++)
            {
                IsDigitsOnly(test);
            }
            watch.Stop();
            //Console.WriteLine("IsDigitsOnly: " + watch.Elapsed);
            isdigitsonly.Add(watch.Elapsed);
            watch.Reset();
            watch.Start();
            for (int i = 0; i < 1000000; i++)
            {
                regex.IsMatch(test);
            }
            watch.Stop();
            regexss.Add(watch.Elapsed);
            watch.Reset();
            //   Console.WriteLine("Regex: " + watch.Elapsed);
     
            Console.Write("---------------------% " + (Convert.ToDecimal( say)/ 999 * 100).ToString("N2") + "---------------------------");
            Console.CursorLeft = 0;
        }
        Console.WriteLine();
        Console.WriteLine($"TryParse: {tryparse.Max(t => t.Ticks)}");
        Console.WriteLine($"IsDigitsOnly: {isdigitsonly.Max(t => t.Ticks)}");
        Console.WriteLine($"Regex: {regexss.Max(t => t.Ticks)}");
        Console.WriteLine();
        Console.WriteLine($"TryParse Avg: {tryparse.Average(t => t.Ticks)}");
        Console.WriteLine($"IsDigitsOnly Avg: {isdigitsonly.Average(t => t.Ticks)}");
        Console.WriteLine($"Regex Avg: {regexss.Average(t => t.Ticks)}");
        Console.WriteLine();
        Console.WriteLine($"TryParse Min: {tryparse.Min(t => t.Ticks)}");
        Console.WriteLine($"IsDigitsOnly Min: {isdigitsonly.Min(t => t.Ticks)}");
        Console.WriteLine($"Regex Min: {regexss.Min(t => t.Ticks)}");
        Console.ReadLine();
    }
    static bool IsDigitsOnly(string str)
    {
        foreach (char c in str)
        {
            if (c < '0' || c > '9')
                return false;
        }
        return true;
    }
}

试试下面的代码:

bool isDigitsOnly(string str)
{
   try
   {
      int number = Convert.ToInt32(str);
      return true;
   }
   catch (Exception)
   {
      return false;
   }
}

char.IsDigit(myChar)呢?

非常聪明和简单的方法来检测你的字符串是否只包含数字,是这样的:

string s = "12fg";
if(s.All(char.IsDigit))
{
   return true; // contains only digits
}
else
{
   return false; // contains not only digits
}
public bool CheckforDigits(string x)
{    
    int tr;  
    return x.All(r=> int.TryParse(r.ToString(), out tr));
}