最快的方法来检查string是否只包含数字
我知道一些如何检查这个问题的方法。 正则expression式, int.parse
, tryparse
,循环。
谁能告诉我什么是最快的方法来检查?
需要的只是CHECK ,实际上不需要parsing。
这不是一个问题: 我如何确定一个string是否是一个数字?
问题不仅在于如何识别。 但是关于什么是最快的方法。
bool IsDigitsOnly(string str) { foreach (char c in str) { if (c < '0' || c > '9') return false; } return true; }
可能是最快的方法来做到这一点。
以下是基于相同string的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确实允许前/后空白以及培养特定的符号。 这也是有限的string的长度。
字符已经有一个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);
你可以简单地使用LINQ来做到这一点
return str.All(char.IsDigit);
如果你关心性能,不要使用int.TryParse
和int.TryParse
编写你自己的(简单的)函数(下面的DigitsOnly
或DigitsOnly2
,而不是 DigitsOnly3
– LINQ似乎会产生很大的开销)。
另外,请注意,如果string太长而不能“适合” 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
我喜欢Linq,并在第一次不匹配时退出,你可以这样做
string str = '0129834X33'; bool isAllDigits = !str.Any( ch=> ch < '0' || ch > '9' );
通过使用每个char
而不是每个char
比较,可以快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; }
用于testing的代码(因为结果取决于硬件,版本,顺序等,因此始终是configuration文件):
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; }
英特尔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
空的string和空string的exception -
char.IsDigit
适用于Nd类别中的所有Unicode字符 -
int.TryParse
也允许白色的spase和符号字符
这应该工作:
Regex.IsMatch("124", "^[0-9]+$", RegexOptions.Compiled)
int.Parse
或int.TryParse
不会总是工作,因为string可能包含更多的数字,一个int可以容纳。
如果你打算这样做,不止一次检查使用编译正则expression式是有用的 – 第一次需要更多的时间,但是之后会更快。
你可以在一行LINQ语句中做到这一点。 好的,我意识到这不一定是最快的,所以在技术上没有回答这个问题,但这可能是最简单的写法:
str.All(c => c >= '0' && c <= '9')
可能最快的方法是:
myString.All(c => char.IsDigit(c))
注意:如果你的string是空的,那么它将返回True ,这是不正确的(如果你不认为空有效的数字/数字)
您可以尝试使用正则expression式通过使用C#中的.IsMatch(string input, string pattern)
方法testinginputstring以仅具有数字(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是否只包含数字是这样:
string s = "12fg"; if(s.All(char.IsDigit)) { return true; // contains only digits } else { return false; // contains not only digits }
试试这个代码:
bool isDigitsOnly(string str) { try { int number = Convert.ToInt32(str); return true; } catch (Exception) { return false; } }
public bool CheckforDigits(string x) { int tr; return x.All(r=> int.TryParse(r.ToString(), out tr)); }
怎么样char.IsDigit(myChar)
?