0

今日、私はその理由を理解できるという奇妙な問題に遭遇しました。次のコンソールプログラムを使用します。

internal class Program
    {
        private static void Main(string[] args)
        {
            string s1 = GenerateRandomCode(8);
            string s2 = GenerateRandomCode(8);
            string s3 = GenerateRandomCode(8);
        }

        public static string GenerateRandomCode(int length)
        {
            string charPool = "ABCDEFGOPQRSTUVWXY1234567890ZabcdefghijklmHIJKLMNnopqrstuvwxyz";
            StringBuilder rs = new StringBuilder();
            Random random = new Random();

            for (int i = 0; i < length; i++)
            {
                rs.Append(charPool[(int)(random.NextDouble() * charPool.Length)]);
            }

            return rs.ToString();
        }
    }

プログラムのにブレークポイントを設定してプログラムを実行すると、s1、s2、s3の値はすべて等しくなります。たとえば、s2にブレークポイントを設定すると、返される値は異なります。

ある種の並行性の問題のように見えますか?どうしたの?

ありがとう

4

4 に答える 4

2

乱数ジェネレーターは実際には完全にランダムではありません。同じシード値が与えられると、複数のインスタンスが同じランダムシーケンスを生成します。

ランダムコンストラクターのMSDNドキュメントよりも優れているとは言えません

「デフォルトのシード値はシステムクロックから取得され、有限の解像度を持ちます。その結果、デフォルトのコンストラクターの呼び出しによって連続して作成されるさまざまなランダムオブジェクトは、同じデフォルトのシード値を持ち、したがって、同じセットを生成します。この問題は、単一のRandomオブジェクトを使用してすべての乱数を生成することで回避できます。また、システムクロックによって返されるシード値を変更し、この新しいシード値をRandom(Int32 )コンストラクタ。詳細については、Random(Int32)コンストラクタを参照してください。」

したがって、あなたの場合、Randomインスタンスをクラスレベルのフィールドまたは関数パラメーターとして保持し、それを1回だけインスタンス化する必要があります。

于 2012-06-01T06:53:35.727 に答える
1

Randomへの各呼び出しでnewをインスタンス化しGenerateRandomCode、呼び出しにかかる時間が非常に短いため、3つRandomのオブジェクトすべてが同じ時間ベースのシードになります。つまり、すべて同じ最初の値が返されます。オブジェクトのフィールドを作成し、Randomプログラムの開始時に1回だけインスタンス化し、代わりにGenerateRandomCodeそのインスタンスを使用します。これでRandom、を呼び出すと異なる値が取得されますrandom.NextDouble()

于 2012-06-01T06:52:51.780 に答える
1

new Random()の外に呼び出しを引き出しGenerateRandomCodeます。

毎回再作成し、すばやく連続して呼び出すため、同じランダムシード値を取得している可能性があります。

静的にすることも、依存性注入を使用することもできます(渡す)。

それで問題は解決すると思います。

于 2012-06-01T06:52:54.317 に答える
0

理由:シード値が指定されていない場合の乱数インスタンスは、シードDateTime.Now.Ticks値として値を取ります。インスタンスは非常にすばやく連続して再作成されるため、インスタンスには同じティックがシードされます。したがって、同じ乱数。

証明:コードにいくつかのブレークポイントを入れます。次に、実際のランダムな値を取得します。これは、デバッガーがヒットしたときに、F10、F11、またはF5を押すまでの時間が失われるためです。時間の経過を引き起こします。

解決策: Randomクラスの静的インスタンスを作成し、そのNext関数を必要な場所で使用します。

于 2012-06-01T07:00:58.777 に答える