1

私のプログラムは次のことを行う必要があります。

a. 0 から 9 までの 20 個のランダムな整数の配列を生成します。数値 7 が最初に出現する場合はそれを検索し、配列内のその位置を報告します。

b. 部分 a の計算を 1000 回繰り返し、配列内の各位置について、配列内で最初に出現する 7 がその位置にある回数を報告します。

ただし、プログラムを実行するたびに、次のような奇妙な結果が得られます (毎回異なります)。

  1. どの位置にもセブンが見つかりません
  2. 1 つの位置で 1000 の 7 が見つかり、他の場所では 7 は見つかりませんでした
  3. 2 つの位置で数百の 7 が見つかりましたが、他の場所では見つかりませんでした。

私のプログラムの何が問題なのか、誰にも分かりますか?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace Week_6_Project_2
    {
    class Program
    {

    static int intArrayLength = 20;
    static int[] resultsArray = new int[intArrayLength];

    public static Array generateRandomArray() {
        int[] randomNumberArray = new int[intArrayLength];
        Random random = new Random();
        int popcounter = 0;
        while (popcounter < intArrayLength) {
            randomNumberArray[popcounter] = random.Next(0, 10);
            popcounter += 1;
        }
        return randomNumberArray;
    }

    public static void searchForSevens()
    {
        int counter = 0;
        int[] randomArray = (int[])generateRandomArray();
        while (counter < intArrayLength)
        {
            if (randomArray[counter] == 7)
            {
                resultsArray[counter] += 1;
                counter = intArrayLength;
            }
            counter += 1;
        }
    }
    static void Main()
    {
        int searchCounter = 0;
        while (searchCounter < 1000)
        {
            searchForSevens();
            searchCounter += 1;
        }

        int displayCounter = 0;
        while (displayCounter < intArrayLength)
        {
            Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, resultsArray[displayCounter]);
            displayCounter += 1;
        }
        Console.ReadLine();

    }
    }
    }
4

5 に答える 5

3

Randomメソッドを呼び出すたびに、新しいインスタンスをインスタンス化していますgenerateRandomArray。乱数ジェネレーターは現在の時間をシードとして使用するため、2 つのRandomインスタンスを同時にインスタンス化すると、同じ数値が生成され、予期しない結果が発生します。

問題を解決するには、インスタンスを 1 つだけインスタンス化Randomし、プライベート フィールドに格納して、メソッドを呼び出すたびに再利用する必要がありますNext

于 2013-09-28T22:02:26.600 に答える
-1

私は答えませんが、複数の Random インスタンスが必要であると考えている人々の類推を試みます...

6 枚の紙に 1 ~ 6 の乱数を入力する必要があるとします。これを自問してみてください。仕事をするのに6個のサイコロが必要ですか、それとも1個必要ですか? 複数のサイコロが必要だと答えた場合は、次のことを自問してください。毎回同じサイコロを投げる代わりに、異なるサイコロを投げることはどのくらい違うか、またはよりランダムですか?

つまり、サイコロで 1 を投げた場合、次にサイコロを振っても、他の数字よりも 1 になる可能性が低くなることはありません。直感に反しますが、数学的にも統計的にもそうです。

于 2013-09-29T18:34:48.867 に答える
-1

Random()私が推測する問題は、現在の時間をシードとして使用するという事実に起因しています。また、計算は非常に高速に行われるため、new Random()呼び出されるたびに同じ時間が使用されます。したがって、同じ数列が得られます。

これを修正するには、自分でシードを設定する必要があり、サイクルごとに増分するだけで十分です。

long base = DateTime.Now.TotalMilliseconds;
Random rand = new Random(base+searchCounter);

.. そんな感じ。

于 2013-09-28T22:01:47.617 に答える
-2

Random元のコードでは、メソッドを立て続けに呼び出している[OP の元のコードに基づく壊れた例]ため、同じ番号でメソッドをシードし、重複した「乱数」番号が発生します。静的メンバーを作成すると、その単一のインスタンスを作成するだけなので、ランダム性が保証されます。

このような単一の静的インスタンスを作成してみてくださいrandom【静的メンバー例】 .

static readonly Random Random = new Random();

これに基づいて、あなたの特定の問題を解決する方法を次に示します。

using System;

namespace Week_6_Project_2
{
    class Program
    {
        // ******************************************
        // THIS IS A SINGLE INSTANCE OF Random.
        // read below as to why I'm seeding the instantiation of Random();
        static readonly Random Random = new Random(Guid.NewGuid().GetHashCode());
        // ******************************************

        private const int IntArrayLength = 20;
        static readonly int[] ResultsArray = new int[IntArrayLength];

        public static Array GenerateRandomArray()
        {
            var randomNumberArray = new int[IntArrayLength];

            var popcounter = 0;
            while (popcounter < IntArrayLength)
            {
                randomNumberArray[popcounter] = Random.Next(0, 10);
                popcounter += 1;
            }
            return randomNumberArray;
        }

        public static void SearchForSevens()
        {
            var counter = 0;
            var randomArray = (int[])GenerateRandomArray();
            while (counter < IntArrayLength)
            {
                if (randomArray[counter] == 7)
                {
                    ResultsArray[counter] += 1;
                    counter = IntArrayLength;
                }
                counter += 1;
            }
        }
        static void Main()
        {
            var searchCounter = 0;
            while (searchCounter < 1000)
            {
                SearchForSevens();
                searchCounter += 1;
            }

            var displayCounter = 0;
            while (displayCounter < IntArrayLength)
            {
                Console.WriteLine("Number of first occurrence of 7 at position {0} = {1}", displayCounter, ResultsArray[displayCounter]);
                displayCounter += 1;
            }
            Console.ReadLine();

        }
    }
}

についてさらに読むRandom()

上記の答えを超えて、さらにランダム性を確保するためにシードする必要がある場合がありますRandom(int);(私は Guid の HashCode を使用するのが好きです)。これは、デフォルトのシードがドキュメント[microsoft]の有限解像度を持つクロックを使用するためです。クラスが立て続けに複数回インスタンス化される場合 (< 16ms)、クロックから同じシードが取得されます...これは問題を引き起こします。[ランダムな結果を伴う
シード実行の例]Random(int)

「パラメーターなしのコンストラクターを使用して、異なる Random オブジェクトを連続して作成すると、同一の乱数シーケンスを生成する乱数ジェネレーターが作成されます。」

ループの反復ごとに新しい Random をインスタンス化するべきではないと言っているのを聞いてください -- 静的メンバーを使用してください


独自のシードを実装するもう 1 つの正当な理由は、ランダムなシーケンスを再作成する場合です[同じシードに基づく 2 つの同一のリストの例]。シーケンスはシードに基づいているため、同じシードを再利用するとシーケンスが再作成されます。

注: シードは必要ないと言う人もいるかもしれません[リンク]。それは何の害もありませんし、状況によっては助けになることもあります。

于 2013-09-28T22:39:13.777 に答える