判斷一個字符串是否全是數字的多種方法及其性能比較(C#實現)

 摘要:文章:判斷一個字符串是否全是數字的多種方法及其性能比較(C#實現) 摘要:在編程的時候,經常遇到要判斷一個字符串中的字符是否全部是數字(0-9),本來是一個很容易實現的功能,但程序員首先會想到的,發表於北京聯高軟件有限公司技術文章欄目,代碼以高亮顯示。
關鍵字:字符, 數字, 性能, 判斷, time, seconds, isnumeric, int, end, start, 函數, exception, environment, system, tickcount, str

在編程的時候,經常遇到要判斷一個字符串中的字符是否全部是數字(0-9),本來是一個很容易實現的功能,但程序員首先會想到的是,這樣簡單的功能有沒有現成的函數可以用呢?VB.NET中有個IsNumeric(object),C#中只有判斷單個字符的Char.IsNumber(),IsNumeric可以判斷double類型的數字字符串,但無法排除正負號和小數點,如果判斷字符串是否是一個數的話用它挺合適,但不能用來判斷字符串是否全部由數字組成的。沒現成的方法了,只好自己寫函數:
  1. public static bool IsNum(String str)   
  2. {   
  3.      for(int i=0;i<str.Length;i++)   
  4.      {   
  5.           if(!Char.IsNumber(str,i))   
  6.           return false;   
  7.      }   
  8.      return true;   
  9. }   
  10. //或用正則表達式:"^\d+$"   
  11. //還可以用Int32.Parse()拋出的Exception來判斷:  
  12. try  
  13. {   
  14.      Int32.Parse(toBeTested);   
  15. }   
  16. catch  
  17. {   
  18.      //發生了異常,那麼就不是數字了。   
  19. }  

 

那麼哪一種方法最好呢?各有優劣。我順手寫了一個程序對每一種方法所需要的時間進行了測試。測試程序Main()內容如下:

  1. class ExapleOfLegalsoft   
  2. {   
  3.      public void fun()   
  4.      {   
  5.           Regex isNumeric = new Regex(@"^\d+$");   
  6.           int times = 10000000;   
  7.           int start, end;   
  8.           int i;   
  9.           string toBeTested = "6741s"; 
  10.           #region Test user function   
  11.           start = System.Environment.TickCount;   
  12.           for (i = 0; i < times; i++)   
  13.           {   
  14.                 TimingTest.IsNum(toBeTested);   
  15.           }   
  16.           end = System.Environment.TickCount;   
  17.           Console.WriteLine("User function Time: " + (end - start) / 1000.0 + " Seconds"); 
  18.           #endregion  
  19.           #region Test Regular Expression  
  20.           start = System.Environment.TickCount;   
  21.           for (i = 0; i < times; i++)   
  22.           {   
  23.                 isNumeric.IsMatch(toBeTested);   
  24.           }   
  25.           end = System.Environment.TickCount;   
  26.           Console.WriteLine("Regular Expression Time: " + (end - start) / 1000.0 + " Seconds"); 
  27.           #endregion  
  28.           #region Test Exception   
  29.           start = System.Environment.TickCount;   
  30.           for (i = 0; i < times / 100; i++)   
  31.           {   
  32.                 try  
  33.                 {   
  34.                      Int32.Parse(toBeTested);   
  35.                 }   
  36.                 catch  
  37.                 {   
  38.                      //發生了異常,那麼就不是數字了。   
  39.                 }   
  40.           }   
  41.           end = System.Environment.TickCount;   
  42.           Console.WriteLine("Exception Time: " + (end - start) / 10.0 + " Seconds"); 
  43.           #endregion  
  44.           #region Test VB.NET IsNumeric()   
  45.           start = System.Environment.TickCount;   
  46.           for (i = 0; i < times / 10; i++)   
  47.           {   
  48.                 Microsoft.VisualBasic.Information.IsNumeric(toBeTested);   
  49.           }   
  50.           end = System.Environment.TickCount;   
  51.           Console.WriteLine("VB.NET IsNumeric() Time: " + (end - start) / 100.0 + " Seconds"); 
  52.           #endregion   
  53.      }   
  54. }  
因爲Exception所用的時間太長,所以只測試了1/100,這樣不太嚴謹,但是數量級不會錯的。
三次運行的結果是:
User function Time: 1.938 Seconds
Regular Expression Time: 11.921 Seconds
Exception Time: 600 Seconds
VB.NET IsNumeric() Time: 40.797 Seconds
User function Time: 1.953 Seconds
Regular Expression Time: 12.016 Seconds
Exception Time: 590.6 Seconds
VB.NET IsNumeric() Time: 40 Seconds
User function Time: 2.000 Seconds
Regular Expression Time: 12 Seconds
Exception Time: 595.3 Seconds
VB.NET IsNumeric() Time: 39.69 Seconds
平均時間:
1.964
11.979
595.3
40.162
速度之比依次約爲:303 : 49.7 : 1 : 14.82
結果很明顯,自定義函數速度最快,異常的速度最慢。假如不需要拋異常的話string toBeTested = "67412";結果就成了:
User function Time: 1.922 Seconds
Regular Expression Time: 9.64 Seconds
Exception Time: 3.1 Seconds
VB.NET IsNumeric() Time: 39.07 Seconds
速度之比依次約爲:20.33 : 4.05 : 12.60 : 1
結論:
自定義函數可以獲得最大的靈活性和最高的性能,而且複雜性也不高,是最佳的方法。
正則表達式法和IsNumeric速度在同一個數量級上,但正則表達式可以確定一種字符串的格式,比如規定一定要有或沒有小數點等,而IsNumeric無法做到。
使用異常是應該避免的。建議僅把Exception作爲處理異常的一種手段,而不是作爲控制流程的一種手段。測試也表明,當有異常拋出時,要消耗大量的資源。
IsNumeric是現成的函數,用起來最省事,只能判斷所給的參數是否是數值(boolean/byte/int16/int32/int64/single/double/decimal),無法作進一步的要求(是否有小數點等)。但IsNumeric的參數是object,不侷限於string。
寫到這裏,我不禁想,還有沒有比自定義函數更快的方法呢?答案是肯定的。在前面的自定義函數中,用的是Char.IsNumber()函數,這個函數不僅能判斷標準ASCII碼中的"1",甚至對全角中文的"1"的判斷也是true,可見Char.IsNumber()判斷的是所有的Unicode字符中的數字,其他語言中的數字也包括了。假如我們只允許ASCII中的"1"的話,我們可以這樣改:
  1. public static bool IsNum(String str)   
  2. {   
  3.  for(int i=0;i<str.Length;i++)   
  4.  {   
  5.   if(str[i]<"0" || str[i]>"9")   
  6.     return false;   
  7.  }   
  8.  return true;   
  9. }  

 

測試結果也令我吃驚,這樣比原來的IsNum速度提高了近10倍,平均執行時間是0.205秒!
結果全部出來了,該怎樣選擇大家心裏肯定已經有數了,我也不需要再說什麼了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章