2016-02-01 48 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