プロが教えるわが家の防犯対策術!

現在srandをした後、randを使って乱数を作っているのですが、
最低100万、できれば1000万の精度の乱数を作りたいのです。
しかしどうやら上限が32768までらしく、困っております。

今の私には32768の乱数を306個作って足す程度しか思いつかず。
何かもっと負担の少なくシンプルな方法はないでしょうか・・?

A 回答 (8件)

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/ …
こちらからCのライブラリソースがダウンロードできます。

手軽さを求めるなら、Xorshift アルゴリズムは、たった10行程度のCの関数でrandより遙かに優れた乱数が得られます。
http://ja.wikipedia.org/wiki/Xorshift
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 14:10

とりあえずまともな乱数が欲しければメルセンヌツイスターを使え。


# http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ …

暗号用途向きではないけど、シミュレータ等の一般用途なら十分な精度があるし、それほど遅いわけでもない。
乱数は下手な加工をすると分布が乱れる。素人が変に捻ったことをするより、評価の固まったものを使う方が良い。

参考URL:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ …
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 14:16

直接の回答ではなくて、ごめんなさい。



少なくとも、乱数を足して乱数を作るのは、良くない方法です。
(もしも、ランダムな乱数が必要なら)

乱数をたくさん足すと、結果は、32768 / 2 × 306 に集中することになるからです。

逆に、正規分布するような乱数を作るのに、乱数を足したりすることがあります。
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 14:15

標準ライブラリの乱数のアルゴリズムはそんなに難しいものではありません。



http://ja.wikipedia.org/wiki/%E6%93%AC%E4%BC%BC% …

自作してもたいした労力ではないと思います。
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 14:13

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/ …
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 14:12

9999×10+9999



こんなんでいいかな?
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 14:11

RAND_MAXは0x7fff(15ビット)で定義されている通り、0~32767で返ってきますので


1回目のrand結果を15ビット左へシフトし、2回目のrand結果を足せば
30ビット分(0x3fffffff)の乱数になりますがいかがでしょうか。
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 13:58

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

    • good
    • 0
この回答へのお礼

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

お礼日時:2010/11/25 13:41

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