2013-02-18 4 views
3

Мне нужен метод, который возвращает случайные числа от min до max, оба числа включительно. Я нашел некоторый код в статье .NET Matters: Tales from the CryptoRandom от Стивена Toub и Шон Фаркаш, где метод будет выглядеть примерно так:RNGCryptoServiceProvider с min и max включительно

// Note - maxValue is excluded! 
public static int GetRandomIntBetween(int minValue, int maxValue) 
{ 
    if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue"); 
    if (minValue == maxValue) return minValue; 

    var rng = new RNGCryptoServiceProvider(); 
    var uint32Buffer = new byte[4]; 
    long diff = maxValue - minValue; 

    while (true) 
    { 
     rng.GetBytes(uint32Buffer); 
     uint rand = BitConverter.ToUInt32(uint32Buffer, 0); 
     const long max = (1 + (long)int.MaxValue); 
     long remainder = max % diff; 
     if (rand < max - remainder) 
     { 
      return (int)(minValue + (rand % diff)); 
     } 
    } 
} 

Моя попытка сделать MaxValue включено:

public static int GetRandomIntBetween(int minValue, int maxValue) 
{ 
    if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue"); 
    if (minValue == maxValue) return minValue; 

    // Make maxValue inclusive. 
    maxValue++; 

    var rng = new RNGCryptoServiceProvider(); 
    var uint32Buffer = new byte[4]; 
    long diff = maxValue - minValue; 

    while (true) 
    { 
     rng.GetBytes(uint32Buffer); 
     uint rand = BitConverter.ToUInt32(uint32Buffer, 0); 
     const long max = (1 + (long)int.MaxValue); 
     long remainder = max % diff; 
     if (rand < max - remainder) 
     { 
      return (int)(minValue + (rand % diff)); 
     } 
    } 
} 

Выглядит странно, но кажется, что я могу сохранить первые две проверки в том виде, в каком они есть, и он все еще работает, хотя семантика немного отличается. Также результаты данных выглядят хорошо. Я что-то пропустил, или мое изменение нормально?

PS - Я прошу об этом, потому что генерация случайных чисел, очевидно, является довольно деликатной задачей и хотела бы быть уверенным, что мой подход правильный.

ответ

1

Ваши изменения верны afaik, случайное целое число между [a,b] является случайным целым числом от [a,b+1[.

Пока MaxValue не int.MaxValue, то ++ будет переполнение, поэтому было бы безопаснее не менять MaxValue и переместить изменения в расчете дифференциала:

long diff = (long)maxValue - minValue + 1; 

Однако второй проверка исходной функции, очевидно, неверна, если minValue == maxValue, возврат minValue не является значением только между minValue и maxValue.

0

Look at my solution (click there)

Вы можете добавить дополнительный метод к классу:

public int NextInclusive(int minValue, int maxValue) { 
     return Next(minValue, maxValue + 1); 
}