如何在GUID范围内确定性地生成n个唯一数字?

时间:2018-01-13 15:39:39

标签: c# algorithm random

一个具体的例子。

如果我的范围是1-300,那么如何使用GUID "EDAAE218-FBF0-4B66-AEAF-FB036FBF69F4"在该范围内生成5个唯一数字。将相同的算法应用于GUID应该导致每次都选择相同的5个数字。

输入不必是GUID,它只是作为某种键。

我想解决的问题的一些背景。我有一个硬编码的值列表,其中包含大约300个左右的元素。我试图找到一种方法从这个列表中选择20个元素,它们总是产生相同的元素。

我的想法是生成可以分发给多个用户的GUID。当这些用户将GUID输入到应用程序中时,将为每个人返回相同的20个元素。

1 个答案:

答案 0 :(得分:1)

guid实际上是128位数字。因此,只要表示数字所需的位数少于guid中的位数(128),就可以轻松完成此操作。你不需要对guid或类似的东西进行哈希处理。

编辑:

既然我知道你需要什么(即从guid派生出一个独特的种子,你可以这样做) - 但你可以同样分发一个32位的数字并避免guid-to-int转换

EDIT2:根据上述评论中的建议使用GetHashCode。

编辑3:制作唯一的数字。

 static void Main(string[] args)
 {
     var guid = new Guid("bdc39e63-5947-4704-9e12-ec66c8773742");
     Console.WriteLine(guid);
     var numbers = FindNumbersFromGuid(guid, 16, 8);

     Console.WriteLine("Numbers: ");
     foreach (var elem in numbers)
     {
         Console.WriteLine(elem);
     }
     Console.ReadKey();
 }

 private static int[] FindNumbersFromGuid(Guid input,
     int maxNumber, int numberCount)
 {
     if (numberCount > maxNumber / 2) throw new ArgumentException("Choosing too many numbers.");
     var seed = input.GetHashCode();
     var random = new Random(seed);
     var chosenSoFar = new HashSet<int>();
     return Enumerable.Range(0, numberCount)
         .Select(e =>
         {
             var ret = random.Next(0, maxNumber);
             while (chosenSoFar.Contains(ret))
             {
                 ret = random.Next(0, maxNumber);
             }
             chosenSoFar.Add(ret);
             return ret;
         }).ToArray();
 }