#include <stdlib.h> int rand(void); int rand_r(unsigned int *seedp); void srand(unsigned int seed);
glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):
rand_r(): _POSIX_C_SOURCE || _XOPEN_SOURCE
srand() 関数は、 rand() 関数で作られる疑似乱数整数系列の新しい種として、 その引き数の値を使用する。 これらの関数を使用して作られた疑似乱数系列は、 同じ値を引き数として srand() を呼ぶことで、 再現することが可能である。
種の値が与えられない場合には、 rand() 関数は 自動的に 1 を種とする。
rand() 関数は再入可能 (reentrant) ではない、つまりスレッド・セーフではない。 なぜなら、この関数は隠し状態を持っており、呼び出される度に変更するからである。 ちょうどこの隠し状態が次の呼び出し時の乱数の種として使われるようなものである。 実際にはもう少し複雑かもしれないが。スレッドを使用するアプリケーションで 再現可能な動作をさせたい場合には、この隠し状態が原因で再現性がなくなる。 rand_r() 関数は unsigned int 型の変数へのポインタを引き数にとり、 この変数を状態格納用に使用する。 状態数が非常に小さいので、この関数はあまりよい擬似乱数生成器とは言えないだろう。 代わりに drand48_r(3) を使うとよい。
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)) では、次のようなコメントがなされている。
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 章 (乱数) を見よ。ここでは、 たくさんの実用的な話題についても深く網羅されている。
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; }