1

重複の可能性:
1 つの乱数のみを生成する乱数ジェネレーター

大規模なシステムで観察された動作を次のコード シーケンスにまとめました。

for (int i = 0; i < 100; i++)
{
    Random globalRand = new Random(0x3039 + i);

    globalRand.Next();
    globalRand.Next();
    int newSeed = globalRand.Next();

    Random rand = new Random(newSeed);
    int value = rand.Next(1, 511);
    Console.WriteLine(value);
}

これを Visual Studio 2012 ターゲット .NET 4.5 から実行すると、316 または 315 のいずれかが出力されます。これを 100 反復を超えて拡張すると、値がゆっくりと減少することがわかります (314、313...)。誰もが「ランダム」と考えるでしょう。

編集

StackOverflow には、乱数がランダムではない理由を尋ねる質問がすでにいくつかあることを認識しています。ただし、これらの質問には、a) Random オブジェクト インスタンスにシードを渡さない (または同じシードを渡す) か、b) NextInt(0, 1)2 番目のパラメーターが排他的境界であることを認識していないなどの問題があります。これらの問題はどちらも、この質問には当てはまりません。

4

4 に答える 4

5

これは、基本的に長い(無限の)数値のリストを作成する疑似乱数ジェネレーターです。リストは決定論的ですが、ほとんどの実際的なシナリオでは、順序はランダムとして扱うことができます。ただし、順序はシードによって決定されます。

あなたが達成できる最もランダムな振る舞いは(常に正しくするのが難しい派手なズボンのトリックなしで)同じオブジェクトを何度も再利用することです。

コードを以下に変更すると、よりランダムな動作になります

Random globalRand = new Random();

for (int i = 0; i < 100; i++)
{
    globalRand.Next();
    globalRand.Next();
    int newSeed = globalRand.Next();

    Random rand = new Random(newSeed);
    int value = rand.Next(1, 511);
    Console.WriteLine(value);
}

その理由は、疑似乱数ジェネレータの背後にある数学は、基本的には無限の数のリストを作成するだけだからです。

これらの数字の分布はほぼランダムですが、それらが来る順序はそうではありません。コンピューターは決定論的であり、真の乱数を(支援なしで)生成できないため、この数学の天才は、これらの数のリストを生成できる関数を生成しました。これらの関数は、多くのランダム性を持っていますが、シードが順序を決定しています。

同じシードが与えられると、関数は常に同じ順序を生成します。各順序に近い2つのシード(closeは関数が使用されるプロパティである可能性があります)が与えられると、リストはリストの最初のいくつかの番号でほぼ同じになりますが、最終的には大きく異なります。

于 2012-10-15T18:51:05.613 に答える
1

最初の乱数を使用して2番目の乱数を生成します。これ以上「ランダム」にはなりません。提案されているように、これを試してください。

また、提案されているように、ループ内でランダムオブジェクトを生成する必要はありません。

    Random globalRand = new Random();

    for (int i = 0; i < 100; i++)
    {
        int value = globalRand.Next(1, 511);
        Console.WriteLine(value);
    }
于 2012-10-15T18:52:29.183 に答える
0

これは時間ベースであると私は信じているので、プロセスが非常に高速に実行されている場合、ループ内にRandom()新しいインスタンスを作成し続けると同じ答えが得られます。ループの外側を作成してRandom()みて、を使用して次のような答えを取得してください。Random().Next()

Random rand = new Random(); 

for (int i = 0; i < 100; i++) 
{ 
    int value = rand.Next(); 
    Console.WriteLine(value); 
} 
于 2012-10-15T18:58:41.127 に答える
0

パラメータがないと、Random c'tor は現在の日付と時刻をシードとして使用します。通常、現在の日付と時刻が変更されたことを内部タイマーが検出する前に、かなりの量のコードを実行できます。したがって、同じシードを繰り返し使用していて、同じ結果が繰り返し得られます。ソース: http://csharpindepth.com/Articles/Chapter12/Random.aspx

于 2012-10-15T18:58:07.713 に答える