MQL4でXorShiftによる疑似乱数生成。-2147483648 > -2147483647-1 という不思議。
真面目な用途での乱数生成は、メルセンヌ・ツイスターが推奨で、MT4 であれば これ、Excel であれば、Excel乱数生成アドインがあります。
ただ、どうしても MQL4のみで、MathRand() より良さそうな乱数を使いたい時のために、XorShift による実装を用意しました。
int XorShiftRand(int seed = 123456789) { static int x = 123456789; static int y = 362436069; static int z = 521288629; static int w = 88675123; if(seed != 123456789) x = seed; int t; t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); return(w);// w = -2147483648~2147483647 }
使い方は、
XorShiftRand(GetTickCount());
で、最初に seedを設定し、以降は、XorShiftRand() で、-2147483648〜2147483647 の整数乱数を得ることができます。
ちなみに、1億回実行した時の実行時間は以下の傾向です。
関数 | 実行時間(ms) |
MathRand | 3479 |
XorShiftRand | 7660 |
gsl_rng_uniform | 16724 |
極端に遅くなることは無いようです。
-2147483648 > -2147483647-1 という不思議。
実用性はさておき、XorShift を調べていて気づいたのが MQL4 の不思議な挙動です。
int a = -2147483648; int b = -2147483647-1; if(a > b) Print("a > b");// TRUE
↑ a と b は等しいはずなのに、a が大きくなります。
この現象は、int 型の最小値 -2147483648 のときのみ起こる・・・と信じたいところですが、未確認です。
int a = -2147483648.0; // 実数表記
int a = 0x80000000; // 16進表記
↑変則的に、このように宣言すれば、a == b が成立します。
これは苦肉の策ですが、、変数の型で定義される末端の数値を扱うときは注意しましょう。。orz