4

最小から最大までの乱数を返すメソッドが必要です。両方の数値が含まれます。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));
        }
    }
}

奇妙に見えますが、最初の 2 つのチェックをそのままにしておくことができ、セマンティックがわずかに異なっていても機能するようです。結果データも良さそうです。私は何かを逃しましたか、それとも私の変更は大丈夫ですか?

PS-乱数の生成は明らかに非常にデリケートな問題であり、私のアプローチが正しいことを確認したいので、これを求めています。

4

2 に答える 2

2

私の解決策を見てください(そこをクリックしてください)

クラスに追加のメソッドを追加できます。

public int NextInclusive(int minValue, int maxValue) {
        return Next(minValue, maxValue + 1);
}
于 2013-06-04T00:20:25.130 に答える
1

あなたの変更は正しいです。[a,b]間のランダムな整数は 間のランダムな整数[a,b+1[です。

maxValue が int.MaxValue でない限り、++ はオーバーフローするため、maxValue を変更せず、変更を diff の計算に移動する方が安全です。

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

しかし、元の関数の 2 番目のチェックは明らかに間違っていminValue == maxValueます。

于 2013-02-18T12:14:00.103 に答える