ループ内の乱数生成の問題
この記事では、ループ内で Random.Next()
を使用するときに発生する一般的な問題、つまり連続した反復で同一の乱数が生成される問題について説明します。 この問題は、複数の Random
オブジェクトが連続してインスタンス化されるときによく発生します。
問題のシナリオ:
次のコード スニペットを考えてみましょう:
<code class="language-csharp">class A { Random rnd = new Random(); public void Count() { int r1 = rnd.Next(-1, 1); int r2 = rnd.Next(-1, 1); // ... further code using r1 and r2 ... } } class B { List<A> listOfA = new List<A>(); public B() { // ... populate listOfA ... foreach (A instance in listOfA) { instance.Count(); } } }</code>
listOfA
にクラス A
の複数のインスタンスが含まれる場合、各 A
オブジェクトは独自の Random
インスタンスを作成します。 高速インスタンス化により、これらの Random
オブジェクトは同じシード値 (多くの場合システム クロックから導出される) を受け取り、同一の乱数シーケンスが生成される可能性があります。
根本原因:
この問題は、デフォルトの Random
コンストラクターがシード処理にシステム クロックに依存していることが原因で発生します。 非常に短い時間枠内に複数の Random
オブジェクトが作成された場合、それらは実質的に同一のシード値を受け取り、その結果、同一の擬似乱数が生成されます。
解決策: 単一のランダムなインスタンス
解決策は簡単です。単一の Random
インスタンスを作成し、それをクラス A
のすべてのインスタンスで再利用します。 これにより、一意で繰り返しのない一連の乱数が確実に生成されます。
修正されたコードは次のとおりです:
<code class="language-csharp">class A { private Random rnd; public A(Random rnd) { this.rnd = rnd; } public void Count() { int r1 = rnd.Next(-1, 1); int r2 = rnd.Next(-1, 1); // ... further code using r1 and r2 ... } } class B { Random rnd = new Random(); List<A> listOfA = new List<A>(); public B() { // ... populate listOfA, passing rnd to the constructor ... foreach (A instance in listOfA) { instance.Count(); } } }</code>
単一の Random
インスタンス (rnd
) を A
クラス コンストラクターに挿入することにより、rnd.Next()
へのすべての呼び出しが同じ適切にシードされたシーケンスから描画されることが保証されます。 これにより、重複する乱数の生成が効果的に排除されます。
以上がなぜランダム.nextは、連続したループイテレーションで同一の値を生成するのですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。