- ベストアンサー
c言語で乱数を扱うときの
乱数を初期化するために srand((unsigned)time(NULL)というのを使いますが これはどういう意味を表してるんでしょうか? timeは1970年から経過した時間を表していることは分かりますし unsignedは符号ビットをなくして表せる数を倍にしてることも分かりますが、 NULLって何のために書いてあるのでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
http://ja.wikipedia.org/wiki/%E6%93%AC%E4%BC%BC%E4%B9%B1%E6%95%B0 実行毎にバラバラにしたければ、srandで毎回変わるような値を種に設定する必要があります。 そのためには「実行の度に変化する値」を使う必要があります。 time関数を使えば、(実行時刻が1秒以上違えば)違う値になるので、よく種として使われます。 他に「実行の度に変化する値」があれば、そちらを使ってもいいです。(OS起動からの経過時間とか、マウスをグリグリ動かしてもらって、その軌跡から計算とか) ※ rand()は使えません。rand()がバラバラになるように指定するものですから。 time関数の仕様は、time関数のマニュアルを読みましょう。 以下の内容はマニュアルに明記されているか、容易に判断できることです。 (unsigned)で型変換しているのは、time関数の戻り値が time_t型であって、srandの引数が求めるunsinged int型では無いからです。 time_tが、符号無しだったり、intよりビット数が多かったりする可能性もあるので、「符号ビットをなくして表せる数を倍」ということではありません。 time関数の引数は time_t*型で、NULLで無い場合は、引数が示すポインタにも結果を返します。 time_t t;として t=time(NULL); と time(&t); とは同じ結果になります。なぜこんなことになっているか、は歴史的な事情です。
その他の回答 (2)
- hanabutako
- ベストアンサー率54% (492/895)
> srand((unsigned)time(NULL)というのを使いますが > これはどういう意味を表してるんでしょうか? srandのマニュアルを読みましょう。 http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=srand&dir=jpman-9.1.2%2Fman§=0 randが作る乱数は疑似乱数といって、計算によってランダムに見える値を作り出すものです。 あらゆる疑似乱数にはその乱数の初期化に使う値 (seed) があり、同じseedを設定すると同じ乱数列が取り出せるようになっています。 srandはrand関数が作る関数のseedを設定する関数です。 現在時刻というのは常に変るので、常に違う乱数列を取り出したい場合に現在時刻をseedとして与えて乱数を作ります。 まぁ、今時srand(time(NULL))なんて、いい乱数列が必要なプログラムでは使わないですね。 randは線形合同法という方法で疑似乱数列を作る関数ですが、線形合同法は乱数のパターンに偏りがあることが知られていて、まともな数値シミュレーションでは使われなくなってきていると思います。そういう用途の場合、メルセンヌツイスター(以下、MTと略記)を使うのが普通でしょう。 http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html また、状況の再現性が大事になりますので、time(NULL)でとってきた適当な値で初期化なんてことは普通しないと思います。 セキュリティ用途で乱数を使うことも多いですが、その場合、アクセスする時刻から内部で使っている乱数seedを類推するのは簡単ですので、安全性としてはかなり弱いと言わざるを得ません。セキュリティ用途の場合、Unix系のシステムなら/dev/urandomから値を取るのが普通ですし、大量の乱数列がそこから必要な場合でも、/dev/urandomの値をseedとしてarc4randomなどを使うのが普通なのではないでしょうか。Windowsの場合でも、CryptGenRandom関数が用意されているはずです。 > NULLって何のために書いてあるのでしょうか? timeのマニュアルを読みましょう。 http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=time&dir=jpman-9.1.2%2Fman§=3 NULLで無い場合はtime_t型変数へのポインタを渡し、その変数にtimeの返り値と同じ値が書き込まれます。 というわけで、マニュアルを読みましょう。 いい乱数列が必要な事例では、MTや/dev/urandomなどの使用を検討しましょう。
- asuncion
- ベストアンサー率33% (2127/6289)
time()の引数の仕様について調べてみましたか?