2016-02-01 82 views
2

我使用Visual Studio 2013iis-8.5.net 4.5.1
在我的項目唯一的編號,我想創建8 digit unique number應當由'hypen'在中間,並與前綴"MNOP-"分開。生成的8 digit應該繼承Cryptography class
我的代碼
產生通過加密

var bytes = new byte[4]; 
var rng = RandomNumberGenerator.Create(); 
rng.GetBytes(bytes); 
int random = BitConverter.ToInt32(bytes, 0) % 100000000; 
var data = "ABCD-" + random.ToString("####-####"); 

我通過'for loop'創造10000的價值,但一些'random variable'返回負值
在此先感謝。

+0

缺少的是一個問題,你已經嘗試和你在哪裏卡住了。 –

+1

8位數字和唯一?選一個。 – Art

+0

var bytes = new byte [4]; var rng = RandomNumberGenerator.Create(); rng.GetBytes(bytes); int random = BitConverter.ToInt32(bytes,0)%100000000;我通過for循環使用了10000個值,但有些數字會給出負值。 – anand

回答

2

有三件事情可以做:

  1. 生成一個隨機值(用十進制數十進制數),並檢查,如果你之前創建它,然後將其存儲到預先生成的號碼清單;
  2. 創建一個400到800 MB的表和shuffle它,然後將它存儲在磁盤上並在表中使用偏移量;
  3. 創建密鑰並將其用於使用與輸入完全相同的輸出的密碼(PRP),並使用計數器,基本上實現了格式保留加密。

你不應該只使用一個隨機數發生器,因爲碰撞的機率會隨着生成的數字量迅速增加。這是因爲生日問題。

這也意味着解決方案1)不適合如果你想生成很多號碼,因爲它可能會失速。想象一下,你只剩下一個可用的數字,你將有一個400 MB的表,它正在嘗試留下那個4字節的條目。其他選項要求您分別存儲表格和偏移量或鍵和計數器。


您目前的方法是不平衡的,因爲它比正數更容易生成更低的數字。此外,您應該重置最高有效位,因爲ToInt32返回有符號,兩個補碼值%剩餘的運算符,而不是模運算符。


OK,因爲只有這個時候,一些C#代碼,來慶祝我的青銅徽章平臺:

namespace StackOverflow 
{ 
    class RandomIDGenerator 
    { 
     private const string FORMAT = "ABCD-####-####"; 
     private const string TEST_FORMAT = "ABCD-###"; 


     private RandomNumberGenerator rng = RandomNumberGenerator.Create(); 
     private byte[] b = new byte[1]; 
     private SortedSet<string> previousIDs = new SortedSet<string>(); 

     private char GenerateRandomDigit() 
     { 
      int x; 
      do 
      { 
       rng.GetBytes(b); 
       x = b[0] & 0xFF; 
      } while (x >= 250); 
      int y = x % 10; 
      return (char) ('0' + y); 
     } 

     private String GenerateRandomID() 
     { 
      StringBuilder sb = new StringBuilder(TEST_FORMAT); 
      for (int i = 0; i < sb.Length; i++) 
      { 
       if (sb[i] == '#') 
       { 
        sb[i] = GenerateRandomDigit(); 
       } 
      } 
      return sb.ToString(); 
     } 

     public String GenerateUniqueRandomID() 
     { 
      string id; 
      do 
      { 
       id = GenerateRandomID(); 
      } 
      while (previousIDs.Contains(id)); 
      previousIDs.Add(id); 
      return id; 
     } 

     public static void Main(String[] args) 
     { 
      RandomIDGenerator gen = new RandomIDGenerator(); 
      for (int i = 0; i < 500; i++) 
      { 
       Console.WriteLine(gen.GenerateUniqueRandomID()); 
      } 

      Console.WriteLine("Put breakpoint here..."); 

      foreach (string id in gen.previousIDs) 
      { 
       Console.WriteLine(id); 
      } 

      Console.WriteLine(gen.previousIDs.Count); 
      Console.WriteLine("Put breakpoint here..."); 
     } 
    } 
} 
+1

對於(1)的策略可以通過始終在'0'到'max_number - already_generated_numbers'範圍內生成隨機數來改進(我不知道在.net中是否有這樣的函數,但是Python有類似的東西),然後從0開始,只計算未使用的數字,直到達到隨機生成的索引。這種線性掃描是昂貴的,但它可以通過二叉搜索樹顯着加快。 –

+0

@ ArtjomB。好的,忘了它。 400 MB適用於內存,您至少可以在某種可預測的時間內執行一個函數。 –

+0

你能舉個例子嗎 – anand