Garbage Collection

塵も積もれば山

目次

Blog 利用状況

ニュース

C++とかC#とか数学ネタを投下していく予定です。

[その他のページ]
日々の四方山話を綴った日記出水の日記帳

書庫

日記カテゴリ

[C++]ランダム大地に立つ

標準のrand関数は余り使わない方がいい、というのは知っているでしょうか。
これは線形合同法に起因する問題で、乱数といいつつも、結構規則正しいという特徴があります。

それを改良した乱数と言うとメルセンヌ・ツイスタが有名ですが、これもちょっとした問題があります。
それは、メモリの消費がかなり多い!

周期が2^19937 - 1 ということは、19937ビットのデータが必要なのです。
その大きさは約2.5KBですが、いくら高品質とはいえ、ちょっと量が多いですね。

それに、2^19937 - 1って数は6000桁以上!
宇宙の果てまで数えられる数の周期が必要な場面はそんなにないでしょう。

そこで、今回紹介するお手頃な乱数が、xorshift。
ソースは以下の通り。

unsigned long xor128(){ 
  static unsigned long x=123456789,y=362436069,z=521288629,w=88675123; 
  unsigned long t; 
  t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) ); 
} 

これだけのソースですが、2^128 - 1という周期をもつ乱数で、たった16バイトしか消費しません。
staticで確保しているx, y, z, wの4つの値を保存しておくだけで、前回の乱数の続きから生成できるため、
シリアライズ化するのも簡単というとてもお手軽かつ便利な乱数です。

なお、乱数の種(seed)ですが、x, y, z, wのすべてが0でなければどんな数でもいいです。
これは、128ビットの数値と見なすと、周期が2^128 - 1ということで、0以外の数値であれば、
循環する数列のどれかの要素になる、というわけです。

そういえば、メルセンヌ・ツイスタを改良したSFMTというものもあるみたいですね。
乱数は奥が深いです。

投稿日時 : 2010年1月19日 22:35

Feedback

# re: [C++]ランダム大地に立つ 2010/01/20 11:29 長月葵

 MTの系譜は最近色々あるみたいですね。
 MTをこえたぜ! って言ってる乱数生成ルーチンもあるみたいです。WELLとか。

# re: [C++]ランダム大地に立つ 2010/01/20 21:43 憂煉

一時期xorshiftを使ってました。
自分にはこの乱数もやっぱり偏りが目立つように思えたので、結局MT使ってます。19937は遅いので521で妥協してたりしますがw
PSPのプログラミングではハードウェア乱数生成器を主に使ってたりします。

# re: [C++]ランダム大地に立つ 2010/01/22 8:41 出水

ちょっと統計取って調べてみたら、
意外にxorshift、バラけた乱数でるなぁという印象です

長期乱数が本当に欲しいなら、こういうの使えばいいじゃん、って思っていますね
数学的には面白いんでしょうけど
http://www.fdk.com/whatsnew-j/release041005-j.html

タイトル
名前
Url
コメント