静的クラスの静的メソッド内に次のコードがあります。
Random r = new Random();
int randomNumber = r.Next(1,100);
これはループ内にあり、同じrandomNumber
を取得し続けます!
ここに何か提案がありますか?
ループで新しいRandom
インスタンスを作成しないでください。次のようなものを試してください:
var rnd = new Random();
for(int i = 0; i < 100; ++i)
Console.WriteLine(rnd.Next(1, 100));
単一のRandom
インスタンスによって生成される乱数のシーケンスは、均一に分散されると想定されています。すべての乱数に対して新しいRandom
インスタンスをすばやく連続して作成することにより、それらに同一の値をシードし、同一の乱数を生成させる可能性があります。もちろん、この場合、生成されるシーケンスは均一な分布にはほど遠いでしょう。
完全を期すために、Random
を再シードする必要がある場合は、新しいシードを使用してRandom
の新しいインスタンスを作成します。
rnd = new Random(newSeed);
私にとって良い種の世代は次のとおりです。
Random Rand = new Random(Guid.NewGuid().GetHashCode());
非常にランダムです。シードもランダムに生成されるため、シードは常に異なります。
何らかの理由で同じRandom
を何度も使用できない場合は、時間自体など、常に変化するもので初期化してみてください。
new Random(new System.DateTime().Millisecond).Next();
ただし、これは悪い習慣です。
編集:デフォルトのコンストラクタはすでにクロックからシードを取得しており、おそらく私たちよりも優れています。 MSDNからの引用:
Random():時間依存のデフォルトのシード値を使用して、Randomクラスの新しいインスタンスを初期化します。
以下のコードがおそらく最良のオプションです。
new Random().Next();
少し遅れますが、System.Randomで使用される 実装 はEnvironment.TickCount
です:
public Random()
: this(Environment.TickCount) {
}
これにより、DateTime.UtcNow.Ticks
をlongからキャストする必要がなくなります。これは、システム起動以降のティックを表さないため、とにかく危険です。ただし、 1、0001(グレゴリオ暦の0001年1月1日の0:00:00 UTC)」。
TestApiのStringFactory.GenerateRandomString
に適した整数シードを探していました
public static Random Rand = new Random(); // this happens once, and will be great at preventing duplicates
これは暗号化の目的には使用しないでください。
これは私のために働く:
private int GetaRandom()
{
Thread.Sleep(1);
return new Random(DateTime.Now.Millisecond).Next();
}
このようにして適切なシードの初期化を行うことができます
Random rnd = new Random((int)DateTime.Now.Ticks);
ティックは一意であり、おそらく値の緩やかなintへのキャストは問題ありません。