- ベストアンサー
(初心者)乱数のことで
使っているソフトはVisual c++です C言語で乱数を使うときにrandom関数を使ったんですが 帰ってくる値が一定なのでネットで検索したら 「メルセンヌ・ツイスタ」 を進めているサイトが多かったので ヘッダーファイルをダウンロードしてみたのですが メルセンヌ・ツイスタを プログラムに組み込む時どのように記述すればいいのか いろいろ試したのですがわかりませんでした メルセンヌ・ツイスタを組み込む構文の仕方を教えてください
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
>きわめて近い値になるんじゃないんですか? まったく同じ値になるんじゃないですか? 理由は(unsigned)time(NULL)が両方とも同じ、つまり ランダムシードが同じ値で、その10番目なので同じ数値になっているのです。 2番目のランダムシードをsrand((unsigned)time(NULL)+1);とすればまた全く違う値になるでしょう。 これはrandの精度の問題ではありません。 #include <stdlib.h> #include <stdio.h> int main() { int i,r1,r2; r1=r2=0; srand((unsigned)time(NULL)); for(i=0;i<10;i++)r1 = rand(); printf("%d\n",r1); srand((unsigned)time(NULL)+1); for(i=0;i<10;i++)r2 = rand(); printf("%d\n",r2); return 0; } 実行結果 1回目 25389 3267 2回目 779 11425 3回目 11425 22072 ちなみにrand自体は0からRAND_MAX(VCだと32767)の値までしか返しませんから、その範囲以外の値にしたいのなら 例えばrand() * (RAND_MAX+1) + rand()等の工夫が必要になります。 ただ乱数の精度を要求するにはrandで不足する場合ももちろんあります。 より厳密な乱数を使いたいなら、ネットを上に乱数生成のソース が転がっています。 boost等にもrandより精度の高い乱数生成の機能が用意されています。
その他の回答 (4)
- sakusaker7
- ベストアンサー率62% (800/1280)
srandやsrandomで初期化をきちんとしていたのなら それも書いていただけると良かったのですが。 順を追っていくと、MTにしても丸っきりの乱数を生成するものではない (ただし線形合同法などに比べれると格段に質よい擬似乱数が得られる)です。 ですので、ごく短時間に時間を種にするということをやるのなら MTを使っても同じ結果になるだけだと思います。 まず一つ目の質問として、擬似乱数の系列を変える必要はあるのでしょうか? もちろん簡単にした例だとは思いますが、#1の補足にある ものをみると、別に系列を新たにしなくてもいいような気がします。 もしどうしても複数の系列で行いたいというのであれば、 ごく短時間でもデータが変わるものを種にしてはどうでしょうか。 UNIXなら /dev/random を読むとかできますが、デバッグのことを考えると、たとえば 一段めとして時間で初期化して、適当に二個数値を取り出して、 それぞれを新たな乱数列の種に使うとか。 cmd.exeのコマンドラインなら %RANDOM% で 0~32767の乱数が得られるのですが これをプログラムからでは取るの画面度でしょう。 二つ目の質問ですが、MTを使おうとしてヘッダーファイルを ダウンロードしたとありますが、具体的にどのサイトの どのファイルでしょうか? わたしが検索したところ、1番目に引っかかったところにあったのは Cでのソースとドキュメントと出力例のもので ヘッダーファイルはなかったのですが?
- asuncion
- ベストアンサー率33% (2127/6289)
srand()は、rand()を使う前に1度だけ実行すれば十分です。
- sakusaker7
- ベストアンサー率62% (800/1280)
MT云々の前に、 > 帰ってくる値が一定なのでネットで検索したら 乱数を生成する前にsrand 呼んでますか?
補足
呼んでいます。 でもそれだとsrandに使った種に対して一定の値しか帰ってこないし 時間を利用してsrandを使っても今度は狭い時間の範囲内しか乱数として取れませんでした
- ibe_tattsu
- ベストアンサー率70% (36/51)
メルセンヌ・ツイスタのことはよく知らないのですが、 srandom関数で初期値を変えたりしましたか? 使っていないのであれば、乱数を生成するための初期値は毎起動時に一定なので、 何回起動しても、同じ乱数が同じように生成されます。 一般的には、 srandom((unsigned)time(NULL)); などをrandom関数を使う前に一度記述して、毎回違う乱数を生成するようにします。
補足
でもその記述方法で記述すると短い間隔で呼び出したときに きわめて近い値しかかえってこない気がするのですが たとえば int i,r1,r2; r1=r2=0; srandom((unsigned)time(NULL)); for(i=0;i<100;i++)r = rand(); printf("%d",r); srandom((unsigned)time(NULL)); for(i=0;i<100;i++)r = rand(); printf("%d",r); (前後略) という構文したとして このときのr1とr2の値は きわめて近い値になるんじゃないんですか? 質問ばかりですいません
補足
失礼しました ソースファイルですね