RNGCryptoServiceProvider包含最小值和最大值

时间:2013-02-18 11:54:48

标签: c# random rngcryptoserviceprovider

我需要一个方法,它从min到max返回随机数,两个数字都包含在内。我在Stephen Toub和Shawn Farkas的文章.NET Matters: Tales from the CryptoRandom中找到了一些代码,其中的方法看起来像这样:

// 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 - 我问这个是因为生成随机数显然是一个非常棘手的问题,并且希望确保我的方法是正确的。

2 个答案:

答案 0 :(得分:1)

您的更改是正确的,[a,b]之间的随机整数是[a,b+1[之间的随机整数。

只要maxValue不是int.MaxValue,那么++就会溢出,所以不更改maxValue并将更改移动到diff的计算会更安全:

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

但是,原始函数中的第二次检查显然是错误的,如果minValue == maxValue,则返回minValue不是minValue和maxValue之间的值。

答案 1 :(得分:0)

Look at my solution (click there)

您可以在课程中添加其他方法:

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