• ベストアンサー

乱数生成、メルセンヌツイスターの使い方

http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html 乱数生成にメルセンヌツイスターというものを使おうとしたのですが、 色々試してみてもいまいち使い方が分かりませんでした。 例えば0から100までの間の乱数を得たい場合などはどのように 書けばよいのでしょうか・・?

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

> 上のコードを元に0~任意の数の乱数を得る関数を > 作ってみたら実行結果が常に同じ値になってしまいます。 > またmac_res様のコードでも実行ごとの乱数の数が全て同じでした・・・。 > > int GetRand( int max ){ i> nt i; > unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4; > init_by_array(init, length); init_by_array はsrandと同じで、(擬似)乱数系列の初期化を行います。 種が同じなら、生成される乱数の値とその順番は同じものになります。 GetRandを呼び出すたびに同じ値で初期化して、同じ系列の値を とってきているのですから、値が同じになるのは当然のことです。 init_by_array (やその類似のもの)は、使用に先立って一回だけ 呼び出せば十分です。また、プログラムの実行ごとに同じ値が で続けてしまうという問題は、乱数系列の初期化を同じ値でやっている ことが原因ですので、srandを起動した時刻を基にした適当な 数値を使って呼び出すような、起動ごとに違う値でもって初期化を 行うようにすれば期待通りの値が得られるのではないでしょうか。

amazontester
質問者

お礼

分かりやすい解説ありがとうございます。 うまくいきました。本当に助かりました。

その他の回答 (2)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.2

mt19937ar.cの最後にmain()が付いているので、これを書き換えれば試験が出来ます。 実際に使うには、main()を消して、init_by_array(),genrand_real2()*100.0 を使用するプログラムに組み込めばよいと思います。 int main(void) { int i; unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4; init_by_array(init, length); printf("\n1000 outputs of genrand_real2()\n"); for (i=0; i<1000; i++) { printf("%10.8f ", genrand_real2()*100.0); if (i%5==4) printf("\n"); } return 0; }

amazontester
質問者

お礼

解答ありがとうございます 上のコードを元に0~任意の数の乱数を得る関数を 作ってみたら実行結果が常に同じ値になってしまいます。 またmac_res様のコードでも実行ごとの乱数の数が全て同じでした・・・。 int GetRand( int max ){ int i; unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4; init_by_array(init, length); return (int)(genrand_real2() * max); } int main(){ for (int i=0; i < 10; i++) { printf("%d\n", GetRand(100) ); } }

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

通常の rand/randomといった関数の使い方、またそれらを使った場合の >例えば0から100までの間の乱数を得たい場合などはどのように の手順についてはわかっていますか? 初期化して、乱数を得るという部分では呼び出す関数の違いがあっても 基本は同じですから、「いまいち使い方がわからない」というのが いまいち理解できません。

amazontester
質問者

お礼

解答ありがとうございます。 初期化して任意の範囲の乱数を得る部分を関数化しようと思ったのですが、 なぜか何度やっても同じ値にしかならないので質問させて頂きました・・。 unsigned long init[4]={0x123, 0x234, 0x345, 0x456} の部分を unsigned long init[4]={rand(), rand(), rand(), rand()} などにすると上手くいったのですが、正しい手順というか 初期化の仕方がどうも理解できないのです。

amazontester
質問者

補足

randについては把握しています。 ただ、MTの場合初期化のキーが必要らしく、randとは 基本的な使い方が違うのではと考えて質問してみました。

関連するQ&A

  • 乱数 メルセンヌツイスターについて

    メルセンヌツイスター法(MT法)について少し調べることになったのですが、メルセンヌツイスターのサイトにC言語のソースがあったので動かしてみました。 確かに乱数が発生するのですが、ソースをみてもどういう動きで乱数を生成してるのかがわかりません。 メルセンヌツイスターはどうやって乱数をつくりだしているのでしょうか? わかる方がいらっしゃいましたら、教えてください。

  • メルセンヌツイスターによる乱数の使い方

    メルセンヌツイスターによる乱数を生成したいのですが、下記コードにすると、mt_rand関数を呼ぶたびにシードが初期化され他乱数が生成されます。 やりたいことは、main関数で一度シード101で初期化した後は、mt_rand関数内では、初期化することなく継続した乱数を生成したいのです。 そのためa_mt_rand関数のようにすると、mtが定義されていないとなるエラーとなります。 namespaceの問題と思うのですが、色々試してみましたが、できませんでした。 どのようにすればできるでしょうか。 vc++11、windows11 使用 参考サイト C++ 乱数ライブラリ std::random の使い方 リンクはうまく貼れませんでした。 #pragma hdrstop #include <iostream> #include <stdio.h> #include <random> using namespace std; void mt_rand(void); int main(int argc, char *argv[]) { int ptr; std::mt19937 mt(101); // メルセンヌツイスターの32ビット版、引数は初期シード std::uniform_int_distribution <> rand100(0, 100); // [0, 99] 範囲の一様乱数 ptr = rand100(mt); printf("ptr=%d\n",ptr); mt_rand(); } void mt_rand(void) { int ptr=0; std::mt19937 mt(101); // メルセンヌツイスターの32ビット版、引数は初期シード std::uniform_int_distribution <> rand100(0, 100); // [0, 99] 範囲の一様乱数 ptr = rand100(mt); printf("%d\n",ptr); } void a_mt_rand(void) { int ptr=0; ptr = rand100(mt); printf("%d\n",ptr); }

  • メルセンヌツイスターを使った2次元乱数

    Mersenne Twisterを使って2次元の乱数を下記のように 生成しています。 1. 乱数を取得. x座標の値とする。 2. 1)で用いた乱数生成を利用して乱数を取得. y座標の値とする。 こうした作成したx,y座標のデータを見ますと、一様性が あまりないように見えます。 これは、2次元の乱数の扱いが間違っているのでしょうか? あるいは、周期が非常に長い乱数でも、2次元的に一様性を 保つためには、凖乱数を使うのがいいのでしょうか。

  • メルセンヌツイスターが使えない

    C++でメルセンヌツイスターのランダムクラスをstaticで作ろうとしたのですがクラスの中に変数を宣言しているにもかかわらず "private: static unsigned int * MyRando::mt" (?mt@MyRando@@0PAIA)" は未解決です。 というエラーが出ました。 このエラーはどうすれば消せるのでしょうか? ちなににstaticをつけない普通のクラスとして宣言すれば使えました。

  • メルセンヌ・ツイスタの乱数生成範囲指定(C++)

    メルセンヌ・ツイスタで乱数の生成範囲を指定したいのですが 以下の方法以外でもっと厳密に乱数を生成できる方法がわかる方いますか? int n; n = genrand_int32() % 10; 上記では0~9までの乱数を求める事が出来ますが、余りは下二桁のみに依存するので 精度が低いのでは?と考えます。 分かる方いましたら宜しくお願いします。

  • 乱数です(・ω・;)

    乱数は作れます(time を使ってやるということです) 今までも、1~6の乱数を生成することなどが出来たのですが、0.0035や0.123などの小数を含む0から1の間の数をどのように生成したらよいでしょうか? よろしくお願いしますm(・ω・)m

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

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

  • 別のSubで生成した乱数の呼び出し

    visual studioのVBAでアプリを作っています。 Private Sub tmr_1(略)で乱数を3つ生成しました。タイマーがtrueの間、乱数を生成し続けるコードを打っています。この乱数を別のSubでも使いたいです。

  • 凖モンテカルロ法 or モンテカルロ + MT

    3次元に広がる物理量を面積分する方法について検討中です。 凖モンテカルロという方法でLDSという数列を用いて計算をすると、積分計算の 誤差の軽減が速まるらしいということがわかりました。原理はまだ勉強中ですが、 対象の空間を区切って、それぞれの細空間に乱数のポイントを配置することが いい方向に働くように見られます。 これに対して、通常のモンテカルロ法でメルセンヌツイスター(MT)を用いた場合との 違いがいまいちわかりません。MTで一様乱数ができるのであれば、凖モンテカルロ のようにする必要はないのでしょうか?

  • アクセスモジュールでの英数 乱数の生成教えて下さい

    整数の乱数生成は確認できています 英数混在の場合の方法がわかりません よろしくお願いします

専門家に質問してみよう