• ベストアンサー

c言語で乱数を扱うときの

乱数を初期化するために srand((unsigned)time(NULL)というのを使いますが これはどういう意味を表してるんでしょうか? timeは1970年から経過した時間を表していることは分かりますし unsignedは符号ビットをなくして表せる数を倍にしてることも分かりますが、 NULLって何のために書いてあるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.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)

回答No.2

> 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% (2126/6288)
回答No.1

time()の引数の仕様について調べてみましたか?

関連するQ&A

  • 乱数について

    Visual Studio2008を使っています。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void){ int i; srand(time(NULL)); i=rand(); printf("%d\n",i); return 0; } 乱数を作るために上のようなプログラミングを作りました。 これを「ソリューションのビルド」すると 【warning C4244: '引数' : 'time_t' から 'unsigned int' への変換です。データが失われる可能性があります。】 と出ます。 このまま行っても乱数が出来るのですが どうしたらいいのでしょうか? 8行目を srand(time_t(NULL)); srand((unsigned)time(NULL)); と変えればいいのでしょうか? time_tでやると乱数が同じ値しか出てきません。 教えてください。

  • 乱数の最大値

    C言語で0~Nまでの乱数を発生させる場合、 srand((unsigned) time(NULL)); rand()%N; とやりますよね。 このやり方だと、発生する乱数はRAND_MAX以下しかできません。 RAND_MAX以上の値を発生させるにはどうすればいいのでしょうか?

  • 乱数で交互に偶数、奇数が、、、。

    C言語で、確率2分の1で0と1を 出そうとして、rand,srand,timeを使って やってみたのですが、ちょうど、0と1が 交互に出てしまいます。何度やっても 変わりません。ただ、1と0が逆になる だけ。こんな感じで0101010101か1010101010 つまり、乱数で奇数と偶数が 交互に発生しているみたいうまくいきません。 なにか、別の方法ありますか? --------------------------------------- srand((unsigned int)time(NULL)); s=rand()%2 これで、やってます。

  • 乱数の取得

    キー操作をした時に複数の乱数を習得させようと思っています。 【キ─操作関数】  int num[3] = {11, 22, 33}; ←初期化のため数字は適当です。  srand((unsigned int)time(NULL))  for(int i=0; i<=3; i++)  {   num[i] = rand % 10;  } 上記のプログラムを書いています。 num[0]、num[1]、num[2]にそれぞれ0~9の乱数が入ると思うのですが、 num[0]にしか乱数が入りません。 num[1]、num[2]には同じ数字(恐らくtimeで取得した数字?)が入っています。 何かお気づきの点がありましたらアドバイスお願い致します。

  • 乱数について・・・

    (1)1,2,3,4の整数のどれかを乱数で発生させる方法 (2)0~1までの実数を発生させる方法 を教えていただけないでしょうか?(a.outするたびに値が変わってほしいです。) ※一応、下のプログラムにあるように実行するたびに違う乱数がanswerに入るようにはできたのですが、いまいち理解できていません。軽い説明や参考URLなども教えてもらえたら助かります。 よろしくお願いします。 #include<time.h> int main() { unsigned short time_a,time_b; unsigned long answer; time_a = time(NULL); time_b = time_a; srand(time_b); answer = rand(); printf("答えは = %d\n",answer); }

  • LSI C-86を利用した時の乱数の挙動について

    C++の6.0を使っています。 srand((unsigned)time(NULL)); を使って1~9の乱数を作らせているのですが、 LSI C-86 Ver 3.30 試食版を使ってexeを作り、 作られた乱数を見ると 1の位置だけがランダムに決まり、   3 2 1 9 8 7 6 5 4 のように、他の数値は順番になってしまいます。 C++上で実行している時は、 全ての数値がランダムに配置されます。 これがどのような理由によるものなのか わかる方がいらっしゃいましたら、 その理由と解決策をお願いします。

  • 完全な乱数を生成する方法

    C言語で乱数を生成するときに、今まで srand(time(NULL)); を使用していたのですが、それだと1秒以内に複数の処理を行った際に、 同一の乱数が生成されてしまいます。 時間にとらわれずに完全にランダムな数字を出現させるにはどのような方法を取るのが簡単なのでしょうか? よろしくお願いします。

  • 乱数発生

    #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) {int y, m, l; srand( (unsigned)time( NULL ) ); y=rand() % 2500 + 1600; m=rand() % 12 + 1; l=rand() % 29 + 1; printf("西暦%d年%d月%d日",y,m,l); return(0); }今回は乱数発生でランダムにだされた西暦年月日をつくりましたが、y=rand() % 2500 + 1600; というのがありこれはyという乱数が2500以下1600以上という意味なのですがなぜかプログラムを実行しても3000いくつとか4000いくつなんてのもでてきます。m=rand() % 12 + 1;はちゃんと12以下1以上でできるのですがなぜですか?本当にわかりません。是非だれか教えてください。

  • 型変換??

    int RANDOM_FUNCTION( int n ) { return (int)( rand() / (float)RAND_MAX * n ); } について Q1.この関数は0からn-1までの乱数を作るそうなのですが,何故ですか? 0<=rand()<=RAND_MAX だから0からnまでの乱数ができるような気がするのですが. Q2.RAND_MAXではなく(float)RAND_MAXとキャストしてある意味は何ですか? Q3.srand((unsigned)time(NULL));と srand((unsigned int)time(NULL));では何か違いますか? Q4.  static int first = 0; if (first == 0){ srand((unsigned)time(NULL)); first = 1; } という処理でsrand((unsigned)time(NULL));は最初の一回だけ呼び出されるようになっているようですが,この部分を srand((unsigned)time(NULL)); というように毎回呼び出すようにするとどうなりますか? 一回呼び出すだけで乱数系列の初期値が呼び出される時に変化しているのですか? Q5.この関数とは関係ない質問ですが,例えば a:int型 b:int型 c:double型 d:float型 のとき d = a / b + c という演算は 1 a:int型,b:int型より(a / b)の結果はint型(小数になった場合は小数点以下切り捨て) 2 (a / b):int型,c:double型,int<doubleより (a / b + c)の結果はdouble型 3 d:float型,『=のあるときは左辺の型に合わせる』よりdはfloat型 というように型変換されているという解釈でいいのでしょうか??

  • C言語でサイコロのプログラムを作ってみたのですが

    まず、以下のような”実行するたびに1~6の数字をランダムに出力するプログラム”を 作ってみたのですが、特定の数字が出てこないのです。 例えば、1と4、2と5、3と6 が出ない ここで気がついた事は、 1、出ない目の2数の差は3であること。 2、乱数自体を表示させたところ、ちゃんと1秒毎に乱数は変わっている。こちらには問題はない 3、約1分間隔で、出ない数字の組み合わせが変わる。 (例えば 1,3,4,6,1,6,3,6,4(2と5が出ない)  →1分間実行し続けると・・・  2,3,6,5,3,2,2,6(1と4が出ない)) この原因は一体なんなのでしょうか・・・ とても気になって仕方がありません。わかる方教えてください。 以下、ソースコードになります #include<stdio.h> #include<time.h> #include<stdlib.h> int func(void); int main(void){ int number=0; number=func(); //サイコロの目の表示 printf("%d\n",number); return 0; } int func(){ //乱数の初期化 srand((int unsigned)time(NULL)); //サイコロの目をランダムで出力し、返す return rand()%6+1; } プログラムの仕組みは パソコンから現在の歴時刻を元に乱数の初期値を変更 ↓ rand関数で適当な値を受け取り、6で割った余剰+1を計算し値を返却する

専門家に質問してみよう