rand - ライブラリコールの説明 - Linux コマンド集 一覧表
名前
rand, srand - 乱数を生成する関数
書式
#include <stdlib.h>
int rand(void);
int rand_r(unsigned int *seedp);
void srand(unsigned int seed);
説明
rand () 関数は 0 から RAND_MAX の間の疑似乱数整数を返す。
srand () 関数は、 rand () 関数で作られる疑似乱数整数系列の新しい種として、 その引き数の値を使用する。 これらの関数を使用して作られた疑似乱数系列は、 同じ値を引き数として srand () を呼ぶことで、 再現することが可能である。
種の値が与えられない場合には、rand () 関数は 自動的に 1 を種とする。
rand ()関数は再入可能 (reentrant) ではない、つまりスレッド・セーフではない。 なぜなら、この関数は隠し状態を持っており、呼び出される度に変更するからである。 ちょうどこの隠し状態が次の呼び出し時の乱数の種として使われるようなものである。 実際にはもう少し複雑かもしれないが。スレッドを使用するアプリケーションで 再現可能な動作をさせたい場合には、この隠し状態が原因で再現性がなくなる。 rand_r ()関数は unsigned int 型の変数へのポインタを引き数にとり、 この変数を状態格納用に使用する。 状態数が非常に小さいので、この関数はあまりよい擬似乱数生成器とは言えないだろう。 代わりに drand48_r (3) を使うとよい。
返り値
rand () と rand_r () 関数は 0 と RAND_MAX の間の数を返す。 srand () 関数は値を返さない。
例
POSIX 1003.1-2003 では、
rand
()と
srand
()の実装例として以下を挙げている。これは、異なる2つのマシンで同じ乱数系列が
必要な場合には便利であろう。
static unsigned long next = 1;
/* RAND_MAX を 32767 と仮定 */ int myrand(void) { next = next * 1103515245 + 12345; return((unsigned)(next/65536) % 32768); }
void mysrand(unsigned seed) { next = seed; }
注意
rand () と srand () の Linux C Library 版は、 random () と srandom () の両関数と同じ乱数生成 アルゴリズムを使用している。そのため、下位のビットは上位のビットと 同じくらいにランダムである。 しかし、旧版の rand ()の実装や、他のシステムの現在の実装では、下位のビットが上位のビットほど ランダムになっていない。移植性を高める場合でも、精度の高い乱数が必要な アプリケーションではこの関数は使用してはいけない。
Numerical Recipes in C: The Art of Scientific Computing
(William H. Press, Brian P. Flannery, Saul A. Teukolsky, William
T. Vetterling; New York: Cambridge University Press, 1992 (2nd ed.,
p. 277))
では、次のようなコメントがなされている。
「1 と 10 の間の乱数を生成したいのであれば、常に
j = 1 + (int) (10.0 * rand() / (RAND_MAX + 1.0));
のように上位ビットを用いること。
j = 1 + (rand() % 10);
のような、下位のビットを用いるような方法は決してしないこと。」
乱数の生成は複雑な話題である。前述の Numerical Recipes in C では実用的な乱数生成を論点とした優れた議論が第 7 章 (乱数) で展開されている。
より理論的な議論については Donald E. Knuth の The Art of Computer Programming ,volume 2 (Seminumerical Algorithms), 2nd ed.; Reading, Massachusetts: Addison-Wesley Publishing Company, 1981 の第 3 章 (乱数) を見よ。ここでは、 たくさんの実用的な話題についても深く網羅されている。
準拠
関数 rand ()と srand ()は SVr4, 4.3BSD, C89, C89, POSIX.1-2001 に準拠している。 関数 rand_r ()は POSIX.1-2001 に由来する。