これを確認する方法をいくつか知っています。正規表現、int.parse
、tryparse
、ループ。
誰が最も速いチェック方法を教えてもらえますか?
必要なのは チェック実際に解析する必要がないです。
これは同じ質問ではありません: 。文字列が数値であるかどうかをどのように特定しますか?
問題は、どのように特定するかだけではありません。しかし、最速の方法は何ですか。
return str.All(Char.IsDigit);
これを確認する方法をいくつか知っています。正規表現、int.parse
、tryparse
、ループ。
誰が最も速いチェック方法を教えてもらえますか?
必要なのは チェック実際に解析する必要がないです。
これは同じ質問ではありません: 。文字列が数値であるかどうかをどのように特定しますか?
問題は、どのように特定するかだけではありません。しかし、最速の方法は何ですか。
return str.All(Char.IsDigit);
回答:
bool IsDigitsOnly(string str)
{
foreach (char c in str)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
おそらくそれを行う最も速い方法でしょう。
char.IsDigit()
IsDigit
はtrue
さらに約300文字を返します。全角10進数字0123
...(中国と日本で一般的)および他の文化からの数字などを含み০১২௧௨௩௪꘤꘥꘦꘧꘨
ます。
return str.All(c => c >= '0' && c <= '9');
return str.All(char.IsDigit);
。メソッドグループの皆さん、こんにちは!
同じ文字列の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はカルチャー固有の記号だけでなく、先頭/末尾の空白も許可することに注意してください。文字列の長さにも制限があります。
int
、TryParseはfalseを返します。
あなたは単にLINQを使用してこれを行うことができます
return str.All(char.IsDigit);
.All
空の文字列に対してはtrueを返し、null文字列に対しては例外を返します。char.IsDigit
すべてのUnicode文字に当てはまります。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);
ただ1つの比較あたりの使用してより速く、約20%とすることができるchar
とfor
の代わりに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;
}
テストに使用されるコード(結果はハードウェア、バージョン、順序などに依存するため、常にプロファイルします):
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.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));
}
}
...次の結果を生成します...
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
これはうまくいくはずです:
Regex.IsMatch("124", "^[0-9]+$", RegexOptions.Compiled)
int.Parse
またはint.TryParse
、intが保持できるより多くの桁が文字列に含まれている可能性があるため、常に機能するとは限りません。
このチェックを複数回行う場合は、コンパイル済みの正規表現を使用すると便利です。最初は時間がかかりますが、その後ははるかに高速です。
これは、1行のLINQステートメントで実行できます。わかりました。これが必ずしも最速であるとは限らないので、技術的には質問に答えませんが、おそらく最も簡単に記述できます。
str.All(c => c >= '0' && c <= '9')
str.All(char.IsDigit)
書くのはさらに簡単ですが、もちろんあなたのコードと同等ではありません。
IsDigit
はユニコードをサポートしています。したがって、Microsoftが実装したときに選択した時間とメモリのトレードオフによっては、チェックにかなりの費用がかかる場合があります。私はそれがネイティブコードに転送すると思います、その移行も非常に高価になる可能性があります。
これは非常に遅くなるかもしれません!しかし、それが私を助けたので、それは誰かを助けると確信しています。
private static bool IsDigitsOnly(string str)
{
return str.All(c => c >= '0' && c <= '9');
}
.IsMatch(string input, string pattern)
C#のメソッドを使用して、数字(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
}
このコードを試してください:
bool isDigitsOnly(string str)
{
try
{
int number = Convert.ToInt32(str);
return true;
}
catch (Exception)
{
return false;
}
}
Convert.ToInt32
o(n)よりも高速で実行されるとしたら、私は非常に驚きます。この仮定を裏付ける証拠はありますか?
文字列を検出する非常に賢明で簡単な方法は、数字しか含まれていないか、この方法です:
string s = "12fg";
if(s.All(char.IsDigit))
{
return true; // contains only digits
}
else
{
return false; // contains not only digits
}