C#乱数ライブラリ

Last modified on Jun 24 2014.

C#で実装した擬似乱数ライブラリのバイナリ及びソースです。

概要

各種擬似乱数生成アルゴリズムのC#による実装です。

動作環境

実装済みアルゴリズム

ダウンロード

Visual Studio 2005のプロジェクトファイル一式を配布しています。 これには、ライブラリソース(C#)、テストプログラムソース(VB)、 及びそれらのコンパイル済みバイナリが含まれます。

ライセンス

短いコードですし、ほとんど全て著名な乱数生成アルゴリズムそのままです。 ですので、著作性を主張できるような部分はほとんどありません。

そのまま使いたい人もいないと思いますが、 どうしても、丸コピーして使いたい人は MITライセンス(条文はMITL.txt)、GPL、 妖精のライセンスの 三者のいずれかを選んで適用してください。

コードには著作権がありますが、アルゴリズムには著作権が存在しないことに注意してください。 同じ動作・アルゴリズムのコードを組むのは著作権の侵害にはあたりません。

説明

C標準のrandよりはましですが、 .Net標準のSystem.Randomは乱数としては満足いくものではありません。 下位ビットが周期的であったり、上位ビットが連続で同じだったりします。 最大値が0x7FFFFFFEであるのも非常に使い勝手が悪い仕様です。 モンテカルロシミュレーションをよく行う身としては、 こんなライブラリではとても耐え切れません。

これらの問題を解決するために、 各種擬似乱数生成アルゴリズムを探し、 C#を用いて実装してみたものがこのライブラリです。 ただの乱数ライブラリですので、 探せばより良いコードも公開されていると思いますが、 一例として、誰かの役に立つこともあるかと思い、公開します。

コード作成にあたり以下の点に重きを置いています。

私のための私のライブラリですので、私が使いやすいようになっています。 他人には使いづらい部分も多分にあると思いますが、 このコードをそのまま他人が使うことを前提としていませんので、 あきらめてください。

アルゴリズムは、できる限り1次ソースから読み解き、同じパラメーターで作っています。 これは自分の勉強のためと、互換性のためです。 同じ種であれば、1次ソースのコードと同じ乱数列得られるようにしています。 ただし、あまりに古い物は1次ソースを取得するのが困難ですので、あきらめました。

アルゴリズムが理解可能であることや、 C#のスタイルを維持することに重点を置いています。 ですので、unsafeは用いていません。 後から読んで理解できるよう、初めての人が読んで何をしたいのかわかるよう、 書き方を心がけました。 コーディングスタイルは、MSDNのサンプル等を参考にしています。

上記範囲内で、できる限り高速化しています。 C#による実装では、これより高速な実装は見つけられませんでした。 ですが、C#は高速な言語ではありません。 CやC++で実装したものをPInvokeした方が速いので、 速度を重要視する場合はこのライブラリの使用はお勧めしません。

前述のように、System.Randomは癖があります。 その癖はそのままでアルゴリズムだけ違うものを使いたい場合のため、 .Net標準のSystem.Randomを、 このライブラリで提供される乱数生成クラスに置き換えるための アダプタークラス(Rei.Random.CompatilizedRandom)も提供しています。

比較

配布しているテストプログラムを用い、 Intel Xeon 5130 2GHz RAM 1GByteの環境で、108回32bitの乱数を生成した時に かかったおよその時間を示します。

Algorithmmsec
Xorshift500
LCG515
RanrotB1047
SFMT199371078
Mersenne Twister1172
System.Random1500
SFMT2160911875
Well2015
Mother-Of-All2609

私の技術力やC#の能力の問題もありますので、 この表からアルゴリズム自体の速度を論じることはできないことに 注意してください。

通常はSFMT19937が良いと思います。 質も周期も速度も、普通の用途には十分でしょう。 特に速い生成ルーチンが欲しい場合はXorshiftがよいと思われます。 周期が2128-1と、少し小さめですが、 普通は問題にならないと思います。

当たり前ですが、SIMDを用いた最適化ができません。 そのせいもあり、SFMTとMersenne Twisterにほとんど差がありません。 ボトルネックはメモリアクセスのようです。

前述したように、速度が重要な用途では CやC++の実装を.Netから呼び出したほうが圧倒的に速くなります。 その場合、当然上記表の順位などは入れ替わると思われます。

更新履歴

2007/10/6 Ver. 1.0.0
  • 公開。

参考資料

SIMD-oriented Fast Mersenne Twister (SFMT)

Mersenne Twisterの新しいタイプ。 SIMDならすごく速いんだが、.Netだとどうも…。

Mersenne Twister: A random number generator (since 1997/10)

言わずと知れたMersenne Twister。 詳しいことはわかりませんが、名前がとにかくかっこいい。

Linear congruential generator - Wikipedia, the free encyclopedia

線型合同法の既定のパラメーターはここから。

mother.c

Mother-Of-Allのおそらく最も古いソース。

The Marsaglia Random Number CDROM including the Diehard Battery of Tests

George MarsagliaによるDiehardテスト。 Mother-Of-Allを含む各種擬似乱数生成器のコードもある。 Mother-Of-Allのパラメーターはここから。

Xorshift RNGs

Xorshiftの論文。

Improved Long-Period Generators Based on Linear Recurrences Modulo 2

Wellの論文。

http://www.iro.umontreal.ca/~panneton/well/

Wellのオリジナル。WELLRNG19937V2.cはバグあり。

Chaotic Random Number Generators with Random Cycle Lengths

Ranrotの詳細説明。

Uniform random number generators by Agner Fog

Ranrotのオリジナルと他の擬似乱数生成器のライブラリ。 現在Ranrotは含まれていない。