[Performance][C#]同時判斷多個字串是否為數值型態

  • 14305
  • 0
  • C#
  • 2009-12-22

[Performance][C#]同時判斷多個字串是否為數值型態

一般來說,在C#中若我們想要判斷字串是否為數值形式。多半我們會利用TryParse、正規表示式這兩種方式來做處理。相關的文章在網路上已經很多了,像是TryParse的方法就可以參閱HOW TO:判斷字串是否表示數值 (C# 程式設計手冊)這篇MSDN文章。

 

這邊摘錄MSDN的範例,簡單的帶過:    


  string s = "108";
  bool result = int.TryParse(s, out i); //i now = 108

 

以上就是判斷字串是否為數值的程式寫法,相信這個簡單的程式大家應該都會寫,這邊就不再深入探討。今天要談的重點是當今天碰到要判斷很多字串是否都為數值時,您會怎摸樣去做?

這邊我大概的提出了幾個我能想到的作法,再對其效能做些比較。

 

方法一

應該是大家最常用的方法,分別判斷所有的字串是否為數值。 


        {
            int tempValue;
            foreach (string value in values)
            {
                if (!int.TryParse(value, out tempValue))
                    return false;
            }
            return true;
        }

 

方法二

主要是把所有字串先合併成一個字串,再用TryParse作數值判斷的動作。(這個方法需特別注意的是,此種合併的作法可能會讓數值溢位。) 
 

方法二之一

不處理負數的情況 


        {
            int tempValue;
            return int.TryParse(string.Join(string.Empty, values), out tempValue);
        }

 

方法二之二

處理負數的情況 


        {
            int tempValue;
            int idx = 0;
            foreach (string value in values)
            {
                values[idx] = value.TrimStart('-');
            }
            return int.TryParse(string.Join(string.Empty, values), out tempValue);
        }

 

方法三

用正規表示式分別判斷其是否為數值。 


        {
            foreach (string value in values)
            {
                if (!Regex.IsMatch(value,@"\d+"))
                    return false;
            }
            return true;
        }

 

 

方法四

把所有字串先合併成一個字串,再用正規表示式作數值判斷的動作。  


        {
            return Regex.IsMatch(string.Join(string.Empty, values), @"\d+");
        }

 

 

效能比較

測試程式如下:    


        {
            //String[] values = InitTestStrings(1);
            String[] values = InitTestStrings(10);
            //String[] values = InitTestStrings(10,1);
            //String[] values = InitTestStrings(10, 2);
            //String[] values = InitTestStrings(10, 3);
            int testCount = 1000000;
            Stopwatch sw = Stopwatch.StartNew();
            for (int idx = 0; idx < testCount; ++idx)
            {
                IsNumeric1(values);
            }
            sw.Stop();
            Console.WriteLine("Method1: " + sw.ElapsedMilliseconds + " ms");

            sw.Reset();
            sw.Start();
            for (int idx = 0; idx < testCount; ++idx)
            {
                IsNumeric2_1(values);
            }
            sw.Stop();
            Console.WriteLine("Method2-1: " + sw.ElapsedMilliseconds + " ms");

            sw.Reset();
            sw.Start();
            for (int idx = 0; idx < testCount; ++idx)
            {
                IsNumeric2_2(values);
            }
            sw.Stop();
            Console.WriteLine("Method2-2: " + sw.ElapsedMilliseconds + " ms");

            sw.Reset();
            sw.Start();
            for (int idx = 0; idx < testCount; ++idx)
            {
                IsNumeric3(values);
            }
            sw.Stop();
            Console.WriteLine("Method3: " + sw.ElapsedMilliseconds + " ms");

            sw.Reset();
            sw.Start();
            for (int idx = 0; idx < testCount; ++idx)
            {
                IsNumeric4(values);
            }
            sw.Stop();
            Console.WriteLine("Method4: " + sw.ElapsedMilliseconds + " ms");
        }

        static string[] InitTestStrings(int count)
        {
            string[] testStrings = new string[count];
            for (int idx = 0; idx < count; ++idx)
            {
                testStrings[idx] = idx.ToString();
            }
            return testStrings;
        }

        static string[] InitTestStrings(int count,int nonValueIndex)
        {
            string[] testStrings = InitTestStrings(count);
            testStrings[nonValueIndex] = "Test";
            return testStrings;
        }

 

帶入以下測試條件 : 

 

其運行結果如下:
image

 

帶入以下測試條件 : 

 

其運行結果如下:

image

 

帶入以下測試條件 : 

 

其運行結果如下:

image

 

帶入以下測試條件 : 

 

其運行結果如下:

image

 

帶入以下測試條件 : 

 

其運行結果如下:

image

 

帶入以下測試條件 :

 

其運行結果如下:
image

 

由以上實驗,我們可以看見的是,在某些條件下,方法二這種先合併字串,再用TryParse的方式效能最佳。某些條件下,先合併字串在集中判斷可以獲得較好的效能。主要取決於字串合併數量的多寡、與第幾個字串不為數值這兩個條件。

實驗下來我們也可以發現,字串處理的OverHead好像比數值判斷來得低很多。因此使用字串合併後再判斷約有7/10的機率可獲取較高的效,另外適時的使用功能不那摸強大的判斷方式,也可以適當的提升效能,而使用正規表示式的方式則是效能最差的判斷方式。

另外一提,有興趣的可以試者把Int.TryParse改為Decimal.TryParse看看,其對效能也有相當的影響,所以依需求用對適當的型別來處理也是很重要的。

 

Link