문자열에 C#의 숫자만 포함되어 있는지 확인하는 가장 빠른 방법
문자열에 숫자만 포함되어 있는지 확인하는 몇 가지 방법을 알고 있습니다.
RegEx,int.parse
,tryparse
, 고리 모양 등
가장 빨리 확인할 수 있는 방법이 무엇인지 누가 말해 줄 수 있습니까?
값만 확인하면 되고 실제로 파싱할 필요는 없습니다.
"digit"이란 구체적으로 ASCII 숫자를 의미합니다.0 1 2 3 4 5 6 7 8 9
.
이 질문은 문자열이 숫자인지 식별하는 것과 동일한 질문이 아닙니다. 이 질문은 식별하는 방법뿐만 아니라 가장 빠른 방법이 무엇인지에 대한 질문이기 때문입니다.
bool IsDigitsOnly(string str)
{
foreach (char c in str)
{
if (c < '0' || c > '9')
return false;
}
return true;
}
아마 그것을 하는 가장 빠른 방법이 될 것입니다.
LINQ를 사용하여 간단히 작업을 수행할 수 있습니다.
return str.All(char.IsDigit);
.All
빈 문자열의 경우 true를 반환하고 null 문자열의 경우 예외를 발생시킵니다.char.IsDigit
는 모든 유니코드 숫자 문자에 대해 참입니다.
다음은 동일한 문자열의 1000000 구문을 기준으로 한 몇 가지 벤치마크입니다.
업데이트 대상release
통계:
IsDigitsOnly: 384588
TryParse: 639583
Regex: 1329571
여기 코드가 있어요, 아이즈디지츠처럼 보여요더 빠른 것만:
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)이 있으며 이를 통해 다음과 같은 작업을 수행합니다.
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);
비교를 한 번만 수행하면 약 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
빈 문자열 및 예외를 생성합니다.null
줄들char.IsDigit
Nd 카테고리의 모든 유니코드 문자에 대해 true입니다.int.TryParse
또한 공백과 부호 문자를 허용합니다.
성능에 관심이 있다면 어느 쪽도 사용하지 마십시오.int.TryParse
도 아니다Regex
- simple 함수를 직접 작성합니다(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));
}
}
...다음 결과를 produces합니다...
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);
}
나는 린크를 좋아하고 첫번째 미스매치에서 퇴장하기 위해서는 이렇게 할 수 있습니다.
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.Parse
아니면int.TryParse
문자열에 int에서 사용할 수 있는 숫자가 더 많이 포함될 수 있기 때문에 항상 작동하지는 않습니다.
이 검사를 두 번 이상 수행할 경우 컴파일된 정규식을 사용하는 것이 유용합니다. 처음에는 더 많은 시간이 걸리지만 그 이후에는 훨씬 더 빠릅니다.
너무 늦게 올 수도 있지만, 누군가에게 도움이 될 거라고 확신해요.
private static bool IsDigitsOnly(string str)
{
return str.All(c => c >= '0' && c <= '9');
}
정규식을 사용하려면 입력 문자열이 숫자(0-9)만을 갖도록 테스트해야 합니다..IsMatch(string input, string pattern)
C#의 메서드입니다.
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)
실패하면 문자열에 숫자만 포함되지 않습니다.또 다른 가능성은 만약 끈이"-12345"
로 변환됩니다.-12345
성공적으로 변환된 숫자가 0보다 작지 않음을 확인하기 위한 검사가 있습니다.
저는 @TheCodeKing의 답변을 약간 변경했습니다.
다음과 같습니다.
forint type 가장 빠른 방법은 TryParse입니다.
롱타입의 가장 빠른 방법은 레젝스입니다.
나의 결과는 아래와 같습니다(칙)
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));
}
언급URL : https://stackoverflow.com/questions/7461080/fastest-way-to-check-if-string-contains-only-digits-in-c-sharp
'source' 카테고리의 다른 글
printk와 pr_info의 차이 (0) | 2023.11.07 |
---|---|
루트(또는 sudo)에서 NVM을 사용할 수 없습니다. (0) | 2023.11.07 |
숫자를 세 부분으로 나누고 그 총합을 원래의 숫자와 일치시키는 알고리즘이 있습니까? (0) | 2023.11.02 |
리눅스에서 syscall 기능을 다시 구현(또는 랩)하려면 어떻게 해야 합니까? (0) | 2023.11.02 |
XML 파일을 어떻게 구문 분석합니까? (0) | 2023.11.02 |