1

I was searching on google for RNGCryptoServiceProvider with examples on how to limit the range between Max and Min, and still get an even distribution. Before I used modulo operator, but sometimes it I get strange values (above Max)... Anyways this code (credit to unknown) seeds Random with a new seed from RNGCCryptoServiceProvider, everytime the method is called. What do you guys think?

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);
}
Half_Baked
  • 340
  • 4
  • 18

3 Answers3

5

There is no point in using an encryption class random generator to seed a regular random generator. (By the principle of the weakest link...) Just use a single instance of the random generator, and reuse it:

private static Random rnd = new Random();

public static int GetRandom(int min, int max) {
  return rnd.Next(min, max);
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
3

You'll want to create your RNGCryptoServiceProvider object once and then re-use that object every time you want a new random number. For instance, you can either pass said object into your GetRandom() method or store it in a class-level field.

As far as the RNGCryptoServiceProvider type itself, it generates good numbers on its own, there's no need to create a Random object and pass in a seed. This should give you a very decent distribution:

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);
}
itsme86
  • 19,266
  • 4
  • 41
  • 57
  • There is an integer overflow in this implementation if `max - min` is too big to be contained in an int. – mschwaig Jul 21 '16 at 18:31
0

It's a better practice to seed your random number generator just one time in your application. I suggest you create a static class for random number generation. The random generation object can yield even distribution just by normal usage. I don't know whats the benefit of seeding the generator with RNGCryptoServiceProvider. I prefer using the time as seeding method as usual. Therefore the following code is my suggestion:

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);
    }
}