• ベストアンサー

乱数の初期化について

Cでモンテカルロシミュレーションを行っています。 乱数Merssenne twisterをつかって、各試行ごとに乱数を 時間で以下のように初期化しています。 init_genrand ((unsigned)time(NULL)) ; だいたい10000~100000回くらいシミュレーションを行う必要があって、 各試行は使用しているPCだと一瞬で終了します。 このときに上記の方法で種を初期化すると、 きちんと確認はしていないのですが、 試行時間が短すぎで種の時間が進んでいないような状態が起こります。 パソコンの時間で初期化する場合、間隔が短すぎると初期化種がかぶる ことはありますか。 もしあるなら、1回の試行時間が短いシミュレーションを各々初期化できる ような初期化の方法を教えていただけないでしょうか。 環境はcore2duo2.16、vista32、コンパイラはVisualC++2008です。 よろしくお願いします。

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

連続投稿ですみません。 もしかして、試行ごとに別のプロセスを起こしているのでしょうか? 状況次第ですが、根本的にやり方に問題があるような気がします。

asjei_77
質問者

お礼

お返事が遅くなって申し訳ありません。 恥ずかしながら大きな勘違いをしていて、 自分が行っていたのは同じプロセス内で変数を初期化しようと いう意味のないことをしようとしていました。 アドバイスは参考にさせていただきます。 ありがとうございました。

asjei_77
質問者

補足

回答ありがとうございました。 別のプロセスではなく、初期値以外は同じプロセスです。 種の種を時間で初期化して使うというのは参考になりました。 やるうえで問題はあるのでしょうか。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

#5 の「プロセス」というのは「処理過程」の意味じゃなくて「(プログラムの) 1回の起動」という意味だと思う. つまり, 「1回の試行を行うプログラム」を 1000~10000回実行するってことじゃなくて, 「1000~10000回くらいシミュレーションをするプログラム」を作るってことでしょう.

asjei_77
質問者

補足

全くその通りでした。 質問以前に根本的に乱数について勘違いしてました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

> time関数の戻り値が同じならそうやってrandで得られる値だって同じじゃないの? srandは1回しか呼ばないことが前提です。

  • Gotthold
  • ベストアンサー率47% (396/832)
回答No.3

Mersenne twisterの内部状態を適当なファイルにでも保存しておいて 2回目以降はその状態を引き継いで使えば良いのでは。 > time関数の結果をsrandに与えて、randで得た値 time関数の戻り値が同じならそうやってrandで得られる値だって同じじゃないの?

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

いっそのこと、time関数の結果をsrandに与えて、randで得た値をinit_genrandに渡すのも一つの手です。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

time()は「秒単位の時間を得る」ので、一瞬で終わってしまうような処理をループで回す場合は全て同じ種になる(秒単位の時間が変わらないので)可能性が高いでしょう。 _ftime()でミリ秒単位の時間が取れるので、そちらを利用するのがよいのではないかと。 http://msdn.microsoft.com/ja-jp/library/z54t9z5f.aspx

asjei_77
質問者

お礼

回答ありがとうございました。 検索するとgetTimeGet関数というのがWindows環境で つかえたので、それを用いて解決しました。_ftime()関数は もっとユニバーサルなCの標準的な関数なのでしょうか。

関連するQ&A

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

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

  • 乱数発生ルーチンの使い方について

    数値計算において一様乱数を発生させるルーチンがいろいろあります。ソースが公開されているものやコンパイラが提供したりするものです。それらを利用する場合、乱数発生のシーズ(種)を与えてそれに応じて動作するというものが多いだろうと思います。そこで質問ですが、10000個の乱数を1回発生させる場合と100個の乱数を100回発生させる場合とで乱数の感じがかなり違います。いずれの場合も100×100の2次元データ(エクセルのシート状)として出力して作図したらその違いが簡単に分かります。この違いの原因はシーズの与え方が1回と100回という違いだろうと思います。100回のシーズの与え方にパターンが出来てしまうからだと思われます。例えば時間を使ってシーズを与えなおすことも考えられますが、今時のPCだとあっという間なのでシーズが同じだから、同じ乱数が100個できてしまいます。乱数を繰り返し発生させるときにその繰り返しの中でパターン化された乱数にならないように発生させる方法がないでしょうか。シーズが要らない乱数生成ルーチンとかですが。あるいはシーズをランダムに取得する方法が含まれたルーチン(シーズがないように見える)などです。あるいは本当にないものなど。メルセンヌツイスターはどうなのでしょうか。一応、フォートランでの利用を考えていますが、言語依存の問題ではないかもと思いますが。 よろしくお願いします。

  • 乱数の取得

    キー操作をした時に複数の乱数を習得させようと思っています。 【キ─操作関数】  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で取得した数字?)が入っています。 何かお気づきの点がありましたらアドバイスお願い致します。

  • 乱数について

    C の入門書を1冊読み終え、簡単なプログラムを作成しようとしているのですが、 早速分からないことが出たので教えて頂ければと思います。 --------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int num; int i = 0; while( i < 4 ){ srand(time(NULL)); num = rand()%100; printf("%d\n", num); i++; } return 0; } --------------------------------------------- 上記を実行したのですが、秒数を乱数の種としているため4回とも同じ値を取得してしまいます。 より高精度に秒数を取得することは可能でしょうか? もしくはこのようなかたちで4回ともに異なる数を得ることが出来る方法がありましたら教えて頂きたいと思います。

  • モンテカルロの並列計算

    乱数を用いたモンテカルロ法について質問です。 周期が10の6乗の乱数を10万個用いてある計算をするとき 下記の二通りで計算を行なった場合、2)ではやはり偏った 乱数を用いていることになるのでしょうか? --------------------------------------------- 1) 10万個の乱数使用計算を一つの計算機で計算 乱数の初期化は1回 --------------------------------------------- 2) 10万個の乱数使用計算を20台の計算機で計算 計算機はそれぞれずらして実行し、時間を乱数の初期化に使用 各計算機にて5000個ずつの乱数使用 ---------------------------------------------

  • C++CLI Randomクラスの初期化

    乱数の生成で悩んでいます。 Random^ rnd = gcnew Random((unsigned)time(NULL)); textBox1->Text = (rnd->Next(66) % 6).ToString(); 上記をボタンクリックで行っているのですが、 ボタンを連打すると2、3回同じ値が続けて出力されます。 ボタンを連打しても、毎回違う値にしたいのですが、方法がわかりません。 アドバイスよろしくお願い致します。「

  • 初期化しているつもりなのに、初期化されずにrand関数の結果を得る

    皆様。こんにちは。 C++で簡単なプログラムを書いていたつもりでしたが、 コンパイルが正常であった後に、 プログラムを動作させてみたら、 自分の意図とは少し異なる結果となり、 どこが違うのか?が どうも自分では分かりかねてしまい、 アドバイスをいただきたく 質問させていただきました。 以下の例にあるように、 「a」と「b」という2文字の間に ランダム関数で作成した「任意の数字」を挟む処理を行い その結果を画面に表示するつもりです。 また、この処理を「num」で指定した回数分だけ 実行させたいと思っていました。 ■表示させようとした結果:「a」+「生成した乱数」+「b」 ■担当プログラム ------------------------------------------------------ for (int i=0; i<num; i++) { std::stringstream keystream ; srand((unsigned)time(NULL)); // 乱数の初期化 int randomnum = rand()% 109999999; // 乱数の生成 keystream << "a" << randomnum << "b" ;    printf(keystream); } ------------------------------------------------------ しかし、実際には、 指定された回数分だけの、 表示結果は得られるものの、 a123456b a123456b a123456b a123456b a123456b 上記例(num=5)のように、 乱数の部分が、全部同じ乱数となっていました。 しかし、forの中で 新たに乱数を生成する際、 生成する前に、 乱数の初期化をしているつもりでいますので、 プログラムを実行させた場合に、 表示させれた結果が、 どうして全て同じ乱数を得ているのか?が分からないでいます。 何かアドバイスいただけるとありがたいです。 宜しくお願い致します。

  • 型変換??

    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型 というように型変換されているという解釈でいいのでしょうか??

  • モンテカルロシミュレーションのプログラムについて

    モンテカルロシミュレーションを用いたタンパク質と低分子の結合実験を行えるプログラム(使用言語:FORTRAN77)を作ろうと考えています。 結合実験の目的はタンパク質上で低分子が結合しやすい部分をさがすことです。 タンパク質上のそれぞれの部分に乱数を振り分けて確率的な試行(低分子をタンパク質に結合させる操作)を何回も繰り返すことで結合しやすい部分を見つけ出そうと考えています。 しかしプログラミングを本格的に始めてまもないということもあり、プログラムを作るための糸口がいま一つ見つかりません。 (例えばタンパク質上の各部分での乱数のふりかた、パソコンによる操作でタンパク質と低分子を結合できるようなプログラムの書き方など) プログラム完成にいたるまでの手順、方法等についてのアドバイスを頂けませんか?

  • PICマイコンによる乱数の表示について

    度々こちらで、お助け頂いております。 さて、今回の主旨はPICマイコンによりLCD表示器へ6個の数字を 表示する方法についてご質問させていただきました。 プログラミングはPIC用コンパイラCCS社のCコンパイラを使用し、 Micro chip社のMPLABと統合動作させています。 一般的なC言語と異なる部分があり、扱づらい面のあるコンパイラです。 では、問題のソースコードを次に記述します。 細部の設定や定義は省いて記述してあります。 1.void main() 2. { 3.int data,i; 4.srand((unsigned)time(ULL)); 5.data = 0; 6.表示器の初期化 7.カーソル位置をHomeへ 8.while(1) 9.{ 10.入力信号判定式 11.for(i = 0; i < 6; i++) 12. { 13. data=rand( )%6 + 1; 14. printf(lcd_data"%3d",data); 15. } 16.入力信号判定式 17.break; 18. } 19. } 以上、これだけのソースコードですが、コンパイルすると、 行番4コードがコンパイルエラーとなります。 (※英語のメッセージは読取れません。(勉強不足)) PICに関するrand( )とsrand( )関数について、いろいろと調べてみましたが、 それらに該当する項目が見当たりません。 そこで、行番4の部分をsrand(data);に変更したら、何とかコンパイル成功します。 それをPICに書込み、ターゲットに実装試験してみると、 100回乱数表示のうち、18回同じ組合せの数が出てしまいます。 どうも、srandの初期化が上手く出来てないみたいですが・・・ 何処が不具合となっているのでしょうか? また、同じソースコードをパソコンの標準Cで試してみると、 130回とも全てランダムに画面表示されます。 そこでどなた様か、PICに詳しい方のお知恵を拝借し、 ご指南頂けるなら、大変幸いに思います。 何卒宜しくお願い申し上げます。

専門家に質問してみよう