web-dev-qa-db-ja.com

C#で疑似乱数ジェネレーターをシードする

C#のRandomクラスのインスタンスのシードが必要です。ほとんどの人が、これに現在の時刻のティックカウンターを使用していることを読みました。ただし、これは64ビット値であり、シードは32ビット値である必要があります。 intを返すGetHashCode()メソッドは、オブジェクトに適度に分散された値を提供する必要があり、これを使用して、ティックの下位32ビットのみを使用しないようにすることができます。カウント。ただし、_Int64_データ型のGetHashCode()については何も見つかりませんでした。

ですから、それほど重要ではないことはわかっていますが、次のことは私が思うほどうまくいくでしょうか(試行錯誤のランダム性は試せません)、またはシードとして_(int)DateTime.Now.Ticks_を使用するのと同じように機能するかもしれません?それとももっと悪くなるのでしょうか?誰がこれに光を当てることができますか。

_int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random r = new Random(seed);
_

編集:なぜシードが必要で、Random()コンストラクターに作業を任せないのですか?同じランダムシーケンスに同じシードを使用する他のクライアントにシードを送信する必要があります。

new Random()はすでに現在の時刻を使用しています。 new Random(Environment.TickCount)と同等です。

ただし、これは実装の詳細であり、.netの将来のバージョンで変更される可能性があります

新しいRandom()を使用することをお勧めします。再現可能な疑似ランダム値のシーケンスを取得する場合にのみ、固定シードを提供します。

既知のシードが必要なので、MSと同じようにEnvironment.TickCountを使用します。そして、それをシードとして他のプログラムインスタンスに送信します。

Randomの複数のインスタンスを短い間隔(16ミリ秒になる可能性があります)で作成する場合、それらを同じ値にシードして、同じ疑似ランダムシーケンスを作成できます。しかし、それはおそらくここでは問題ではありません。この一般的な落とし穴は、Windowsが現在の時刻(DateTime.Now/.UtcNow)とTickCount(Environment.TickCount)を数ミリ秒ごとに更新することによって発生します。正確な間隔は、Windowsのバージョンと実行中の他のプログラムによって異なります。それらが変化しない典型的な間隔は16msまたは1msです。

34
CodesInChaos

need現在の時刻以外のものをシードする場合(この場合、デフォルトのコンストラクターを使用できます)、次のように使用できます。

Random random = new Random(Guid.NewGuid().GetHashCode());
30
steinar

質問のより大きなリストからランダムな質問のセットを選択するために、同様の質問がありました。しかし、時間をシードとして使用すると、同じ乱数が得られます。

これが私の解決策です。

    int TOTALQ = 7;
    int NOOFQ = 5;

    int[] selectedQuestion = new int[TOTALQ];

    int[] askQuestion = new int[NOOFQ];

    /*   Genarae a random number 1 to TOTALQ
     *   - if that number in selectedQuestion array is not o
     *   -     Fill askQuestion array with that number
     *   -     remove that number from selectedQuestion
     *   - if not re-do that - - while - array is not full.    
     */

    for (int i = 0; i < TOTALQ; i++)  // fill the array
        selectedQuestion[i] = 1;

    int question = 0;

    int seed = 1;

    while (question < NOOFQ)
    {       
        DateTime now1 = new DateTime();
        now1 = DateTime.Now;    
        Random Rand = new Random(seed+now1.Millisecond);
         int RandomQuestion = Rand.Next(1, TOTALQ);

         Response.Write("<br/> seed  " + seed + " Random number " + RandomQuestion );



        if (selectedQuestion[RandomQuestion] != 0)      
        {
            selectedQuestion[RandomQuestion] = 0;  // set that q =0 so not to select           
            askQuestion[question] = selectedQuestion[RandomQuestion];
            Response.Write(".  Question no " + question + " will be question " + RandomQuestion + " from list " );
            question++;
        }

        seed++;         

    }
0
Saman