同時刻でも大丈夫な乱数の種の元を考える
関数gettimeofdayはマイクロ秒単位の時刻を得ることができたが、
IEEE Std 1003.1-2008によれば、
> Applications should use the clock_gettime() function instead of the obsolescent gettimeofday() function.
とのこと。obsoleteになりかけ/なってるものは使わない方がいいのだろう。
とはいえ、代替として示されたナノ秒単位の時刻を得られる関数clock_gettimeは、
マクロ_POSIX_TIMERSが定義されておらずMinGWでは実装されていないっぽい?*1
となると、適当な数値を得るために時刻を使うなら標準関数であるtimeということになるので、
時刻以外で乱数の種として使えそうなものを考えてみる。
プログラム中でsrandを呼ぶのは一度であり、
そのプログラムを複数回短期間に実行する状況に対処しようとしているわけで、
それぞれの実行時に異なるものといえばプロセスIDであろう。
ということで、プロセスIDを使ってみる。
ただ、Windows環境でそんなことにならないとは思うが、
連続実行でIDが1ずつ増えたりしないとは完全には保証されていないと思うので、
プロセスID単独で乱数の種にするのではなく、
時刻情報も得て、二つを組み合わせて種にしてみよう。
get_rnd.c
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <time.h> int main(void) { srand((unsigned int)time(NULL) * (unsigned int)getpid()); printf("%d\n", rand()); return 0; }
gettimeofdayを使った時と同じように、二つの情報の積を乱数の種とした。
C:\foo> FOR /L %i IN (1,1,5) DO @get_rnd 10470 545 14148 30076 7794
どうやら上手くいっているようだ。
ちなみに前に示さなかったが、time(NULL)だけをsrandに渡すと、
C:\foo> FOR /L %i IN (1,1,5) DO @get_rnd 22601 22601 22601 22601 22601 C:\foo> FOR /L %i IN (1,1,5) DO @get_rnd 22604 22604 22604 22604 22604
当然こうなる。
*1:要確認