一千萬個為什麽

搜索

RNGCryptoServiceProvider包含最小值和最大值

我需要一個方法,它從最小值到最大值返回隨機數字,包括兩個數字。我在 .NET Matters:CryptoRandom的故事中找到了一些代碼。來自Stephen Toub和Shawn Farkas,該方法看起來像這樣:

// 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 - 我在問這個,因為生成隨機數顯然是一件非常微妙的事情,並且希望確定我的方法是正確的。

最佳答案

您的更改是正確的afaik, [a,b] 之間的隨機整數是 [a,b + 1 [ )之間的隨機整數。

只要maxValue不是int.MaxValue,那麽++就會溢出,所以不更改maxValue並將其更改為diff的計算會更安全:

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

但是,原始函數中的第二個檢查顯然是錯誤的,如果 minValue == maxValue ,則返回的minValue不是專有的minValue和maxValue之間的值。

轉載註明原文: RNGCryptoServiceProvider包含最小值和最大值