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

C# 如何在GUID的范围内确定地生成n个唯一的数字?,c#,algorithm,random,C#,Algorithm,Random,一个具体的例子 如果我的范围为1-300,a如何使用GUID“EDAAE218-FBF0-4B66-AEAF-FB036FBF69F4”在该范围内生成5个唯一的数字。对GUID应用相同的算法应导致每次选择相同的5个数字 输入不必是GUID,它只是充当某种键 我试图解决的问题的背景。我有一个硬编码的值列表,包含大约300个元素。我试图找到一种方法,从这个列表中选择20个总是产生相同元素的元素 我的想法是生成一个可以分发给多个用户的GUID。当这些用户将GUID输入到应用程序中时,将为每个人返回相同

一个具体的例子

如果我的范围为1-300,a如何使用GUID
“EDAAE218-FBF0-4B66-AEAF-FB036FBF69F4”在该范围内生成5个唯一的数字。对GUID应用相同的算法应导致每次选择相同的5个数字

输入不必是GUID,它只是充当某种键

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


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

guid实际上是一个128位的数字。因此,只要表示数字所需的位数小于guid中的位数(128),就可以轻松地执行此操作。您不需要散列guid或类似的内容

编辑:

现在我知道了您需要什么(即从guid派生一个唯一的种子,您可以这样做),但是您可以同样地分配一个32位数字,并避免guid到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();
 }
static void Main(字符串[]args)
{
变量guid=新guid(“bdc39e63-5947-4704-9e12-ec66c8773742”);
控制台写入线(guid);
变量编号=FindNumbersFromGuid(guid,16,8);
控制台。WriteLine(“数字:”);
foreach(数字中的变量元素)
{
控制台写入线(elem);
}
Console.ReadKey();
}
私有静态int[]FindNumbersFromGuid(Guid输入,
int maxNumber,int numberCount)
{
如果(numberCount>maxNumber/2)抛出新的ArgumentException(“选择太多的数字”);
var seed=input.GetHashCode();
var random=新随机(种子);
var chosenSoFar=new HashSet();
返回可枚举范围(0,numberCount)
.选择(e=>
{
var ret=random.Next(0,maxNumber);
while(chosenSoFar.Contains(ret))
{
ret=随机。下一步(0,最大数);
}
chosenSoFar.Add(ret);
返回ret;
}).ToArray();
}

当你把确定性和随机性放在同一句话中时,有些地方似乎不对劲。如果总是相同的输出,那么随机性如何?只要在需要salt密钥的地方使用任何哈希算法即可。GUID将用作盐。其中一个是使用bcrypt-hash抱歉,我的描述很混乱。我已经更新了这个问题,并为这个问题提供了一些上下文。GUID不是我的第一选择-它们应该是唯一的,而不是随机的。您可能正在寻找Mersenne Twister
return Enumerable.Range(0,numberCount)。选择(e=>random.Next(0,maxNumber)).ToArray()
可以很容易地生成重复值。此外,您的算法只使用GUID的前4个字节,而丢弃其他12个字节。更改为使用GetHashCode,这将哈希所有16个字节。另一个选项可能是初始化4个Random实例,然后将这些值散列在一起,从而使用GUID的所有16个字节。从OP提出的问题来看,这已经足够了。好吧,但这是我指出的两个问题中较小的一个,更重要的是它可以经常产生非唯一值(这个问题的标题特别指出OP需要唯一值)。例如,使用GUID
721550ec-b930-4099-a399-34432f102eb8
运行代码会生成值148、148、141、132和22.Fixed。现在生成唯一的数字。