アプリ版:「スタンプのみでお礼する」機能のリリースについて

使っているソフトはVisual c++です
C言語で乱数を使うときにrandom関数を使ったんですが
帰ってくる値が一定なのでネットで検索したら
「メルセンヌ・ツイスタ」
を進めているサイトが多かったので
ヘッダーファイルをダウンロードしてみたのですが
メルセンヌ・ツイスタを
プログラムに組み込む時どのように記述すればいいのか
いろいろ試したのですがわかりませんでした

メルセンヌ・ツイスタを組み込む構文の仕方を教えてください

A 回答 (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より精度の高い乱数生成の機能が用意されています。
    • good
    • 0

srandやsrandomで初期化をきちんとしていたのなら


それも書いていただけると良かったのですが。

順を追っていくと、MTにしても丸っきりの乱数を生成するものではない
(ただし線形合同法などに比べれると格段に質よい擬似乱数が得られる)です。
ですので、ごく短時間に時間を種にするということをやるのなら
MTを使っても同じ結果になるだけだと思います。

まず一つ目の質問として、擬似乱数の系列を変える必要はあるのでしょうか?
もちろん簡単にした例だとは思いますが、#1の補足にある
ものをみると、別に系列を新たにしなくてもいいような気がします。

もしどうしても複数の系列で行いたいというのであれば、
ごく短時間でもデータが変わるものを種にしてはどうでしょうか。
UNIXなら /dev/random を読むとかできますが、デバッグのことを考えると、たとえば
一段めとして時間で初期化して、適当に二個数値を取り出して、
それぞれを新たな乱数列の種に使うとか。

cmd.exeのコマンドラインなら %RANDOM% で 0~32767の乱数が得られるのですが
これをプログラムからでは取るの画面度でしょう。

二つ目の質問ですが、MTを使おうとしてヘッダーファイルを
ダウンロードしたとありますが、具体的にどのサイトの
どのファイルでしょうか?
わたしが検索したところ、1番目に引っかかったところにあったのは
Cでのソースとドキュメントと出力例のもので
ヘッダーファイルはなかったのですが?

この回答への補足

失礼しました
ソースファイルですね

補足日時:2007/05/15 11:13
    • good
    • 0

srand()は、rand()を使う前に1度だけ実行すれば十分です。

    • good
    • 0

MT云々の前に、


> 帰ってくる値が一定なのでネットで検索したら

乱数を生成する前にsrand 呼んでますか?

この回答への補足

呼んでいます。
でもそれだとsrandに使った種に対して一定の値しか帰ってこないし
時間を利用してsrandを使っても今度は狭い時間の範囲内しか乱数として取れませんでした

補足日時:2007/05/15 09:51
    • good
    • 0

メルセンヌ・ツイスタのことはよく知らないのですが、


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の値は
きわめて近い値になるんじゃないんですか?
質問ばかりですいません

補足日時:2007/05/15 09:54
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!