1

重複の可能性:
rand() で常に同じ乱数列を取得するのはなぜですか?

私は C で乱数を生成する実験をしてきましたが、奇妙なことに遭遇しました。それが私のコンパイラだけにあるのかどうかはわかりませんが、 rand() 関数で疑似乱数を生成しようとすると、非常に予測可能な数値が返されます。正確には、前のパラメーターで生成された数値に 3.125 を加えた数値です。説明するのは難しいですが、ここに例を示します。

srand(71);
int number = rand();
printf("%d", number);

これは 270 を返します。

srand(72);
int number = rand();
printf("%d", number);

これは 273 を返します。

srand(73);
int number = rand();
printf("%d", number);

これは 277 を返します。

srand(74);
int number = rand();
printf("%d", number);

これは 280 を返します。

8 桁ごとに 4 ずつ高くなります。それ以外は 3 です。

これは正しいとは言えません。コンパイラに何か問題がありますか?

編集:私はそれを理解しました - 私は一度だけシードする関数を作成し、次にループしてrand()乱数を生成します。皆さん、ありがとうございました!

4

4 に答える 4

3

ここでの混乱は、疑似乱数ジェネレーターの動作に関するものです。

C のような疑似乱数ジェネレータrandは、現在の「状態」を表す数値を持つことによって機能します。関数が呼び出されるたびrandに、次の「状態」番号を生成するために「状態」番号に対していくつかの決定論的計算が行われます。したがって、ジェネレーターに同じ入力 (同じ「状態」) が与えられると、同じ出力が生成されます。

したがって、ジェネレーターに をシードするとsrand(74)、毎回同じ数字の文字列が生成されます。ジェネレーターに をシードするとsrand(75)、異なる数値の文字列などが生成されます。

毎回異なる出力を保証する一般的な方法は、常に異なるシードを提供することです。通常は、ジェネレーターに秒/ミリ秒単位の現在の時刻をシードすることによって行われsrand(time(NULL))ます。

編集: これは、この動作を示す Python セッションです。それは完全に予想されます。

>>> import random

ジェネレーターに同じ番号をシードすると、常に同じシーケンスが出力されます。

>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]
>>> random.seed(500)
>>> [random.randint(0, 100) for _ in xrange(20)]
[80, 95, 58, 25, 76, 37, 80, 34, 57, 79, 1, 33, 40, 29, 92, 6, 45, 31, 13, 11]

異なるシードを与えると、わずかに異なるシードであっても、数値は古いシードとはまったく異なりますが、同じ (新しい) シードを使用しても同じです。

>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]
>>> random.seed(501)
>>> [random.randint(0, 100) for _ in xrange(20)]
[64, 63, 24, 81, 33, 36, 72, 35, 95, 46, 37, 2, 76, 21, 46, 68, 47, 96, 39, 36]

プログラムを毎回異なる動作にするにはどうすればよいでしょうか? 同じシードを指定すると、常に同じように動作します。time.time()呼び出すたびに異なる数値を生成する関数を使用できます。

>>> import time
>>> time.time()
1347917648.783
>>> time.time()
1347917649.734
>>> time.time()
1347917650.835

したがって、 を呼び出して再シードし続けるとtime.time()、シードが毎回異なるため、毎回異なる数のシーケンスを取得します。

>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[60, 75, 60, 26, 19, 70, 12, 87, 58, 2, 79, 74, 1, 79, 4, 39, 62, 20, 28, 19]
>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[98, 45, 85, 1, 67, 25, 30, 88, 17, 93, 44, 17, 94, 23, 98, 32, 35, 90, 56, 35]
>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[44, 17, 10, 98, 18, 6, 17, 15, 60, 83, 73, 67, 18, 2, 40, 76, 71, 63, 92, 5]

もちろん、絶えず再シードするよりも、一度シードしてそこから継続する方が良いでしょう:

>>> random.seed(time.time())
>>> [random.randint(0, 100) for _ in xrange(20)]
[94, 80, 63, 66, 31, 94, 74, 15, 20, 29, 76, 90, 50, 84, 43, 79, 50, 18, 58, 15]
>>> [random.randint(0, 100) for _ in xrange(20)]
[30, 53, 75, 19, 35, 11, 73, 88, 3, 67, 55, 43, 37, 91, 66, 0, 9, 4, 41, 49]
>>> [random.randint(0, 100) for _ in xrange(20)]
[69, 7, 25, 68, 39, 57, 72, 51, 33, 93, 81, 89, 44, 61, 78, 77, 43, 10, 33, 8]
于 2012-09-17T20:50:22.337 に答える
0

rand()擬似乱数ジェネレーターによって実装されます。

連続した呼び出しによって生成される数値の分布はrand()、乱数であるという特性を持ちますが、順序は事前に決定されています。「開始」番号は、提供するシードによって決まります。

PRNG には単一のシードのみを指定する必要があります。複数のシードを指定すると、ジェネレーターのランダム性が根本的に変わる可能性があります。さらに、同じシードを何度も提供すると、すべてのランダム性が削除されます。

于 2012-09-17T20:51:34.387 に答える
0

を呼び出すたびrand()に、定義済みの順序で次の番号が返されます。開始番号は に提供されたシードsrand()です。そのため、乱数ジェネレーターではなく、疑似乱数ジェネレーターと呼ばれます。

于 2012-09-17T20:49:43.733 に答える
0

実装に関係なく「乱数」を生成することは、発散無限シーケンスに依存しています。無限シーケンスは、ランダム関数のシードを使用して生成され、その性質上、実際には疑似ランダムです。これにより、数値が関数に与えるシードに実際に大きく依存する理由が説明されます。

一部の実装では、シーケンスは 1 つだけであり、シードはシーケンスの開始メンバーです。他には、シードに応じて異なるシーケンスがあります。シードが提供されない場合、シードは内部の「クロック」によって決定されます。

乱数の上限と下限をそれぞれ と で使用すると、数値が切り捨てられrandValue % upperBoundますrandValue + lowerBoundRandom の実装はHash Functionsに非常に似ています。アーキテクチャに応じて、ランダム値の上限は、ユーザーが低く設定しない場合に実行できる最大の整数/倍精度に応じて設定されます。

于 2012-09-17T21:54:44.800 に答える