Java の乱数としてメルセンヌツイスタを使ってみた

zemclip

素人に毛が生えた程度ですが、確率を扱う機会が割とあります。

今回、確率が絡む「プログラマブルな」問題について汎用解を求め、それをシステム化する事になりました。

用途は意思決定であり、有効桁数が数桁~7桁程度の「実用解」が要求されるため、方程式を解くのではなくモンテカルロ法的アプローチにより広範な「問題」に対応させ、また、現時点で予測できない構造の問題にも容易に対応できる設計としました。

もともとは、知る人ぞ知る Object Pascal 言語の雄「Delphi」で15年前に書いたプログラムの焼き直しのつもりだったのですが、時代も時代ということで Java へ移植し、このタイミングで対応可能な問題の幅を広げる事にしたのです。

Javaへの移植にあたり、乱数の検証を軽んじていた、というか、適当な検証しかせず乱数の分散が微妙だなぁ。と思いながらもそのまま突っ切ってしまった結果、完成してから計算結果の収束速度が遅い事に面喰い、

「ああ、大昔は学生向けに Pascal を推奨している教育機関も多かっただけあって、当時の Delphi の乱数はしっかりしていたんだろうか。」

と疑うハメに。

Delphi の Extended 型は、3.6 x 10^-4951 ~ 1.1 x 10^4932 という途方もない範囲の数値を「精度の割には高速に」扱う事ができ、なんと乱数もこの型で返ってくるのです。

Java で大きな数を扱おうと思って軽く調べたら BigDecimal とかいういかにも遅そうなクラスが出てきて頭痛が・・・・

ともかく、Delphi 版ではこれだけの精度の値を流用してうにゃうにゃと演算をしていたので、Java 版の収束が遅いのは精度の問題なのかと疑ったのですが、検証したところ、現状扱っている程度の確率なら Java の double 精度でも十分すぎると判りました。もっとも、精度が足らないなら、値の領域ごとに再帰的にクラスタリングしてやれば良いだけの話ではあるんですが。

あとは分散の程度が悪いのだろうか。と思い、いろいろ探してみたところ、

Mersenne Twister : A random number generator

と、より高速な

SIMD-oriented Fast Mersenne Twister (SFMT)

が、目に留まったので使ってみました。

乱数の品質も Java 言語の Math.random より良く、速度も SMFT は、なんと Math.random より高速でした。(@Java 6 SE Update 13)

これのおかげで幸せになれそうです。

余談ですが、最近はまっている JavaFX Mobile 1.2 for Windows Mobile Early Access 2 でも動作しました。

てっきり JavaFX Mobile では J2ME CDC レベルのAPIしか使えないと思っていたんですが。java.lang.Math 使えるんですね。というわけで、モバイルでゴリゴリシミュレータまわしたりなんかして遊んでいる今日この頃だったりします。

※2013/9/19 画像リンク切れ修正

Hatena Pocket Line

コメントを記入