RNGCryptoServiceProvider: generate random numbers in the range [0, randomMax)

I wrote the following code to generate random numbers in the range [0, int.MaxValue], but I was not sure how to limit the range to [0, randomMax) while maintaining a uniform distribution:

private static int GetNextInt32(this RNGCryptoServiceProvider random)
{
  var buffer = new byte[sizeof(int)];
  random.GetBytes(buffer);
  return Math.Abs(BitConverter.ToInt32(buffer, 0));
}

Thank.

+5
source share
4 answers

Here is one way to do this: http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=775 . See the “Creating a System.Random Replacement” section.

Please note, however, that using a module operator may not be the best way to ensure good distribution. Perhaps the best way:(int)(NextDouble() * (MaxValue - 1));

. buffer 00 00 00 80, int.MinValue, Math.Abs .

, GetBytes RNGCryptoServiceProvider Random.Next. GetBytes, , . , .

+4

Java nextInt .

, . , . .

( ) # :

public static int GetNextInt32(this RNGCryptoServiceProvider rng, int maxValue)
{
    if (maxValue < 1)
        throw new ArgumentOutOfRangeException("maxValue", maxValue, "Value must be positive.");

    var buffer = new byte[4];
    int bits, val;

    if ((maxValue & -maxValue) == maxValue)  // is maxValue an exact power of 2
    {
        rng.GetBytes(buffer);
        bits = BitConverter.ToInt32(buffer, 0);
        return bits & (maxValue - 1);
    }

    do
    {
        rng.GetBytes(buffer);
        bits = BitConverter.ToInt32(buffer, 0) & 0x7FFFFFFF;
        val = bits % maxValue;
    } while (bits - val + (maxValue - 1) < 0);

    return val;
}
+3

MSDN , Random, RNG:

http://msdn.microsoft.com/en-us/magazine/cc163367.aspx

( . 2007 "Tales from CryptoRandom". . , , . -.)

+1

, , :

    private static RNGCryptoServiceProvider _RNG = new RNGCryptoServiceProvider();  

    private static int GetNextRnd (int min, int max)
    {
        byte[] rndBytes = new byte[4];
        _RNG.GetBytes(rndBytes);
        int rand = BitConverter.ToInt32(rndBytes, 0); 
        const Decimal OldRange = (Decimal)int.MaxValue - (Decimal)int.MinValue;
        Decimal NewRange = max - min;
        Decimal NewValue = ((Decimal)rand - (Decimal)int.MinValue) / OldRange * NewRange + (Decimal)min;
        return (int)NewValue;
    }

int , .

I know this old post, but I ran into a similar problem, and this soul worked for me.

0
source

All Articles