• ベストアンサー

32768以上の乱数を作りたいのですが

現在srandをした後、randを使って乱数を作っているのですが、 最低100万、できれば1000万の精度の乱数を作りたいのです。 しかしどうやら上限が32768までらしく、困っております。 今の私には32768の乱数を306個作って足す程度しか思いつかず。 何かもっと負担の少なくシンプルな方法はないでしょうか・・?

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

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.6

0~32767の乱数二つ(a,b)から、a*32768+b」という計算をすれば、0~1,073,741,823(0~10億)の範囲の乱数になります。 なお、「306個足す」や「2乱数のかけ算」は、やってはいけません。 それをやると、分布が一様ではなくなってしまいます。 (たとえば1~6な乱数源があるとします。この範囲の乱数を2つ足すと2~12の数値が出てきますが、この分布は一様ではなく、7が出やすく2や12は出にくいという偏ったものになります。また、1~6な乱数を2つ掛けると、1~36の数値が出てきますが、7とか11とか…35とか、絶対に出てくることのない数値が数多くでてきます。) 以上は、一般論的な乱数の数値範囲の拡張方法です。 ですが、通常のC/C++の標準ライブラリのrand関数はあまり精度がよくないので、 乱数2数の組を使うのはあまり薦められません。 (2数が全く無関連なら「a*32768+b」は一様な乱数になるのですが、 実際にはrand()関数はある乱数とその次の乱数に関連性があるため、「a*32768+b」は一様ではなく、偏りがでてきてしまいます) ですので、rand を使うのはやめて、別の乱数関数を使ったほうが良いかと思います。 精度の良い乱数が欲しいのなら、メルセンヌツイスタを使うのが良いでしょう。 http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index-jp.html こちらからCのライブラリソースがダウンロードできます。 手軽さを求めるなら、Xorshift アルゴリズムは、たった10行程度のCの関数でrandより遙かに優れた乱数が得られます。 http://ja.wikipedia.org/wiki/Xorshift

noname#202167
質問者

お礼

とても詳しい説明ありがとうございます。 勉強になりました。 今回は手軽で負担が少なそうなXorshiftというのを使わせて頂こうと思います。 ありがとうございました。

その他の回答 (7)

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.8

とりあえずまともな乱数が欲しければメルセンヌツイスターを使え。 # http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html 暗号用途向きではないけど、シミュレータ等の一般用途なら十分な精度があるし、それほど遅いわけでもない。 乱数は下手な加工をすると分布が乱れる。素人が変に捻ったことをするより、評価の固まったものを使う方が良い。

参考URL:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html
noname#202167
質問者

お礼

ご回答ありがとうございます。 より高い精度が欲しくなった場合こちらを利用させて頂こうと思います。

回答No.7

直接の回答ではなくて、ごめんなさい。 少なくとも、乱数を足して乱数を作るのは、良くない方法です。 (もしも、ランダムな乱数が必要なら) 乱数をたくさん足すと、結果は、32768 / 2 × 306 に集中することになるからです。 逆に、正規分布するような乱数を作るのに、乱数を足したりすることがあります。

noname#202167
質問者

お礼

数式はよくわかりませんが・・集中する事はうっすら想像しておりました。 それを利用する事すらあるのですね。 ご指摘、ありがとうございました。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

標準ライブラリの乱数のアルゴリズムはそんなに難しいものではありません。 http://ja.wikipedia.org/wiki/%E6%93%AC%E4%BC%BC%E4%B9%B1%E6%95%B0 自作してもたいした労力ではないと思います。

noname#202167
質問者

お礼

今の私には少々難しいようです・・でも自作も手なのですね。 ご回答ありがとうございました。

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.4

int val = (RAND_MAX + 1) * rand() + rand(); RAND_MAXが32767なら0~1073741823までの乱数が求まります。 RAND_MAXが32767(=2進で111 1111 1111 1111)、15bitが有効という前提であれば int val = (rand() << 15) | rand(); としても同じです。 http://ja.wikipedia.org/wiki/Rand に書かれているようにrandの精度は低いです。 もし乱数の精度を求めるなら、ほかのランダム生成を利用した方がよいです。 http://www.math.sci.hiroshima-u.ac.jp/~m-MAT/MT/VERSIONS/C-LANG/TANDO/MTC/readme.html

noname#202167
質問者

お礼

randは精度が低いのですね。 ご回答ありがとうございました。

  • Cupper-2
  • ベストアンサー率29% (1342/4565)
回答No.3

9999×10+9999 こんなんでいいかな?

noname#202167
質問者

お礼

ご回答ありがとうございます。

  • remwind
  • ベストアンサー率50% (1/2)
回答No.2

RAND_MAXは0x7fff(15ビット)で定義されている通り、0~32767で返ってきますので 1回目のrand結果を15ビット左へシフトし、2回目のrand結果を足せば 30ビット分(0x3fffffff)の乱数になりますがいかがでしょうか。

noname#202167
質問者

お礼

ご回答ありがとうございます。 かなり軽そうで発想の勉強になりました。ありがとうございます。

  • chupark
  • ベストアンサー率41% (90/218)
回答No.1

乱数を足すことをかんがえておられるなら、乱数同士を掛け算すれば、足し算よりはまだ効率がよさそうな気がします。

noname#202167
質問者

お礼

ご回答ありがとうございます。 必要な精度によってはそれもありなのですね。 ありがとうございました。

関連するQ&A