这种生成随机数的方法有多“好”?

时间:2013-05-17 19:29:05

标签: c# random cryptography rngcryptoserviceprovider

我在google上搜索RNGCryptoServiceProvider,其中包含如何限制Max和Min之间范围的示例,并且仍能获得均匀分布。在我使用modulo运算符之前,但有时它会得到奇怪的值(高于Max)... 无论如何,每次调用该方法时,此代码(信用未知)种子随机使用来自RNGCCryptoServiceProvider的新种子。你们有什么感想?

public static int GetRandom(int min, int max)
{
  byte[] b = new byte[sizeof(int)];
  new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
  int i = BitConverter.ToInt32(b, 0);
  Random r = new Random(i);
  return r.Next(min, max);
}

3 个答案:

答案 0 :(得分:5)

使用加密类随机生成器为常规随机生成器播种是没有意义的。 (根据最薄弱环节的原则......)只需使用随机生成器的单个实例,并重用它:

private static Random rnd = new Random();

public static int GetRandom(int min, int max) {
  return rnd.Next(min, max);
}

答案 1 :(得分:3)

您需要创建一次RNGCryptoServiceProvider对象,然后在每次需要新的随机数时重新使用该对象。例如,您可以将所述对象传递到GetRandom()方法或将其存储在类级别字段中。

RNGCryptoServiceProvider类型本身而言,它自己生成好的数字,不需要创建Random对象并传入种子。这应该给你一个非常好的分布:

public static int GetRandom(RNGCryptoServiceProvider rngProvider, int min, int max)
{
    byte[] b = new byte[sizeof(UInt32)];
    rngProvider.GetBytes(b);
    double d = BitConverter.ToUInt32(b, 0) / (double)UInt32.MaxValue;
    return min + (int)((max - min) * d);
}

答案 2 :(得分:0)

最好在应用程序中为随机数生成器播种一次。 我建议你为随机数生成创建一个静态类。随机生成对象可以仅通过正常使用产生均匀分布。我不知道用RNGCryptoServiceProvider播种发生器的好处是什么。我喜欢像往常一样使用时间作为播种方法。因此,以下代码是我的建议:

int randomNumber=Rand.get(min,max);

public static class Rand
{
    private static Random rnd;
    static rand()
    {
        rand=new Random(DateTime.Now.Ticks);
    }
    public static int get(int min,int max)
    {
        return rnd.Next(min,max);
    }
}