1

私はまだC#に不慣れで、コインをX回投げることをシミュレートする短いプログラムを構築しようとしています:

        // Declarations
        int headCount = 0;
        int tailCount = 0;

        // Main Program Logic
        Console.WriteLine("Press enter to begin");
        Console.ReadLine();
        for (int x = 1; x <= 25; x++)
        {
            Random rnd = new Random();
            int flip = rnd.Next(1, 3);
            if (flip == 1)
            {
                Console.WriteLine("Heads");
                headCount++;
            }
            else
            {
                Console.WriteLine("Tails");
                tailCount++;
            }
        }
        Console.WriteLine("Heads came up {0} times.", headCount);
        Console.WriteLine("Tails came up {0} times.", tailCount);
        if (headCount > tailCount)
        {
            Console.WriteLine("Heads wins.");
        }
        else
        {
            Console.WriteLine("Tails wins.");
        }

        // END OF DOCUMENT
        Console.ReadLine();
    }

これで、自分のコードはしっかりしていると確信していますが、プログラムを実行すると問題が発生します。上記のコードでは、for ループが実行されるたびに新しい乱数 (1 または 2) が生成されるという考え方です。実際には、10 回のうち 9 回は、最初に 1 つの数値を生成し、その数値をループの残りの実行に使用します。

誰もが時々、結果が約 50/50 (統計的に期待されるもの) になることがありますが、通常は同じ結果が 25 回繰り返されます。

ループ内でフリップ変数を宣言していることに注意してください。ループ内とループの直前に前後に移動しましたが、変更は効果がないようです。

私は何か間違ったことをしていますか、それとも C# は統計的な異常を捨てるのが好きですか?

4

4 に答える 4

7

その理由は、あなたが電話をかけ続けるからですnew Random()。代わりに、ループの外側でこれを構築し、 THEN を呼び出す必要があります.next(int,int)

 Random rnd = new Random();
 for (int x = 1; x <= 25; x++)
 {
        int flip = rnd.Next(1, 3);
        //do stuff
 }
于 2013-10-14T22:49:05.050 に答える
4

乱数ジェネレーターをループの外でインスタンス化して、乱数を適切に生成できるようにします。

これは、シードが主に CPU クロックに基づいているためです。コンピュータが生成できるのは「疑似乱数」のみであることに注意してください。そのために、シードといくつかの計算を使用します。使用されるシードが同じ時間のものである場合 (ループ内のコードがナノ秒単位で実行されるため)、各乱数は同じです。

ループの外で使用すると、シードは、呼び出されるたびに異なる乱数を作成するための基礎を提供します。

于 2013-10-14T22:52:02.030 に答える
2
Random rnd = new Random();

これはあなたの問題です。ループのたびにジェネレーターを再初期化しています。シードを提供していないため、デフォルトのコンストラクターはミリ秒単位の正確な現在の時刻をシードとして使用します。ループは非常に高速に実行されるため、この数はループのほとんどの反復で同じになり、同じ数を繰り返し生成することになります。

解決策:ループの外に移動します=)

さらに読む:疑似乱数ジェネレーター

于 2013-10-14T22:50:36.630 に答える
0

ループ外で乱数ジェネレーターを初期化する必要があります!

        Random rnd = new Random();
        Console.WriteLine("Press enter to begin");
        Console.ReadLine();
        for (int x = 1; x <= 25; x++)

編集: 実際には、ランダム初期化子を Console.ReadLine() の上に移動するだけで、コードから適切な分布を得ることができました

編集 2:はるかに優れた乱数 が必要な場合は、 RNGCryptoServiceProviderの使用を検討してください。

RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();
var randomByte = new byte[1];
rnd.GetBytes(randomByte);

確かに、Random ほど使いにくい (整数ではなくランダムなバイトが得られるため) が、はるかに優れたランダム性が得られます。ただし、この乱数ジェネレーターは、ランダムを暗号化に使用すべきではないため、暗号化に使用するのに十分です。

于 2013-10-14T22:47:21.013 に答える