web-dev-qa-db-ja.com

ランダムな値を重複させないために、ランダムなクラスをシードする方法

静的クラスの静的メソッド内に次のコードがあります。

Random r = new Random();
int randomNumber = r.Next(1,100);

これはループ内にあり、同じrandomNumberを取得し続けます!

ここに何か提案がありますか?

108
leora

ループで新しい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);
99
Mehrdad Afshari

私にとって良い種の世代は次のとおりです。

Random Rand = new Random(Guid.NewGuid().GetHashCode());

非常にランダムです。シードもランダムに生成されるため、シードは常に異なります。

297
joppiesaus

何らかの理由で同じRandomを何度も使用できない場合は、時間自体など、常に変化するもので初期化してみてください。

new Random(new System.DateTime().Millisecond).Next();

ただし、これは悪い習慣です。

編集:デフォルトのコンストラクタはすでにクロックからシードを取得しており、おそらく私たちよりも優れています。 MSDNからの引用:

Random():時間依存のデフォルトのシード値を使用して、Randomクラスの新しいインスタンスを初期化します。

以下のコードがおそらく最良のオプションです。

new Random().Next();
16
PPC

少し遅れますが、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に適した整数シードを探していました

16
Orphid
public static Random Rand = new Random(); // this happens once, and will be great at preventing duplicates

これは暗号化の目的には使用しないでください。

3
McKay

これは私のために働く:

private int GetaRandom()
    {
        Thread.Sleep(1);
        return new Random(DateTime.Now.Millisecond).Next();
    }
3
Omidoo

このようにして適切なシードの初期化を行うことができます

Random rnd = new Random((int)DateTime.Now.Ticks);

ティックは一意であり、おそらく値の緩やかなintへのキャストは問題ありません。

0
ZedZed