2014-02-22 64 views
1

我有我使用的產生通過創建隨機整數,並將其鑄造charRandom類生成同一序列

public static string GenerateRandomString(int minLength, int maxLength) 
     { 
      var length = GenerateRandomNumber(minLength, maxLength); 

      var builder = new StringBuilder(length); 

      var random = new Random((int)DateTime.Now.Ticks); 

      for (var i = 0; i < length; i++) 
      { 
       builder.Append((char) random.Next(255)); 
      } 

      return builder.ToString(); 
     } 
隨機字符串的方法

的問題是,當我把這種方法頻繁,它正在創建相同的值序列,正如文檔中所述:

隨機數的產生從種子值開始。如果重複使用相同的 種子,則會生成相同的一系列數字。一種產生不同序列的方式是使種子值 與時間有關,由此產生與Random的每個新的實例不同的系列。

正如您所看到的,我正在依賴種子時間並在每次調用方法時創建一個新實例Random。儘管如此,我的測試仍然失敗。

[TestMethod] 
     public void GenerateRandomStringTest() 
     { 
      for (var i = 0; i < 100; i++) 
      { 
       var string1 = Utilitaries.GenerateRandomString(10, 100); 
       var string2 = Utilitaries.GenerateRandomString(10, 20); 
       if (string1.Contains(string2)) 
        throw new InternalTestFailureException(""); 
      } 
     } 

我怎樣才能確保獨立於我稱之爲方法的頻率,序列會「總是」不同?

+0

你根本就在這樣一個緊張的循環中調用它的時候沒有。 [根據文檔](http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx)每毫秒有10,000個刻度。你的循環可能比執行的循環少。因此,每個迭代的「DateTime.Now.Ticks」都是一樣的。你可能不得不找到一個web服務或一些給你一個隨機數的東西......但這不會很快。 –

回答

3

您的測試失敗,因爲GenerateRandomString函數爲DateTime.Now.Ticks更改完成得太快。在大多數系統中,它是quantized at either 10 or 15 ms,這對於現代CPU來說足夠時間來生成100個隨機字符的序列。

插入測試中的一個小的延遲應該解決的問題:

var string1 = Utilitaries.GenerateRandomString(10, 100); 
Thread.Sleep(30); 
var string2 = Utilitaries.GenerateRandomString(10, 20); 
2

你切實做好一樣Random的默認構造函數。它使用Environment.TickCount。看看this MSDN documentationRandom構造函數的例子。它表明,在不同的Random實例的初始化之間插入一個Thread.Sleep,將產生不同的結果。

如果你真的想得到不同的值,我建議你改變爲而不是時間相關的種子值。

1

dasblinkenlight給出了爲什麼會發生這種情況。

現在,你應該這樣做是爲了克服這個問題

public static string GenerateRandomString(Random random , int minLength, 
                int maxLength) 
{ 
    var length = GenerateRandomNumber(random , minLength, maxLength); 

    var builder = new StringBuilder(length); 

    for (var i = 0; i < length; i++) 
     builder.Append((char) random.Next(255)); 

    return builder.ToString(); 
} 

public void GenerateRandomStringTest() 
{ 
    Random rnd = New Random(); 
    for (var i = 0; i < 100; i++) 
    { 
     var string1 = Utilitaries.GenerateRandomString(rnd, 10, 100); 
     var string2 = Utilitaries.GenerateRandomString(rnd, 10, 20); 
     if (string1.Contains(string2)) 
      throw new InternalTestFailureException(""); 
    } 
}