1

私は Google で RNGCryptoServiceProvider を検索して、Max と Min の間の範囲を制限し、均等な分布を得る方法の例を示しました。モジュロ演算子を使用する前に、奇妙な値 (最大値を超える) を取得することがあります... とにかく、このコード (不明のクレジット) は、メソッドが呼び出されるたびに、RNGCCryptoServiceProvider からの新しいシードでランダムにシードします。皆さんはどう思いますか?

public static int GetRandom(int min, int max)
{
  byte[] b = new byte[sizeof(int)];
  new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
  int i = BitConverter.ToInt32(b, 0);
  Random r = new Random(i);
  return r.Next(min, max);
}
4

3 に答える 3

5

暗号化クラスの乱数発生器を使用して通常の乱数発生器をシードしても意味がありません。(最も弱いリンクの原則により...) ランダム ジェネレーターの単一のインスタンスを使用し、それを再利用します。

private static Random rnd = new Random();

public static int GetRandom(int min, int max) {
  return rnd.Next(min, max);
}
于 2013-05-17T19:37:34.590 に答える
3

一度オブジェクトを作成しRNGCryptoServiceProvider、新しい乱数が必要になるたびにそのオブジェクトを再利用する必要があります。たとえば、上記のオブジェクトをGetRandom()メソッドに渡すか、クラスレベルのフィールドに格納できます。

型自体に関してRNGCryptoServiceProviderは、それ自体で適切な数値を生成しますRandom。オブジェクトを作成してシードを渡す必要はありません。これにより、非常に適切なディストリビューションが得られるはずです。

public static int GetRandom(RNGCryptoServiceProvider rngProvider, int min, int max)
{
    byte[] b = new byte[sizeof(UInt32)];
    rngProvider.GetBytes(b);
    double d = BitConverter.ToUInt32(b, 0) / (double)UInt32.MaxValue;
    return min + (int)((max - min) * d);
}
于 2013-05-17T20:03:10.873 に答える