Location : Home > Softwares > NtRand
Title : NtRand Tips
Toolbox Logo

NtRand Tips

  1. ワークシートに出力せずに多数の乱数を発生させるには(Update:2003/04/15)


.ワークシートに出力せずに多数の乱数を発生させるには

 NtRand はもともとメルセンヌ・ツイスター法による擬似乱数発生を Excel 上で利用できるように造られた Add-in ソフトである。実際、1枚のワークシートで収まる程度の乱数発生であれば十分使える。けれども、ワークシート1枚に書き出せないくらいの数の乱数を発生させたい場合(数万〜数10万のオーダー)、ワークシートに出力させるだけでも多大な時間がかかる。
 実際、乱数発生でなくても、ファイルとの入出力や結果のワークシートへの書き出しというのは、VBAマクロを記述する際の速度上のボトルネックになることが多い。これを回避するにはワークシートとの入出力をしないことだ。しかし冒頭に書いたように「NtRand はもともとメルセンヌ・ツイスター法による擬似乱数発生を Excel 上で利用できるように造られた Add-in ソフト」であるので、VBAマクロで NtRand で利用できる関数を呼び出すためには、 VBA からワークシート関数を呼び出すための方法を用いることになる。さて、ここで、Application.run は、VBAでワークシート関数を呼び出す「呪文」だとあきらめてもらおう。また、Tは別途定義する、ほしい乱数の数だとしよう。
 NtRandNorm の引数は、2003年4月時点(Version 2.01)で8つあり、後ろの4つは省略可能だから、最低限これで T この乱数を発生させ、配列 Result に格納されるはずだ。また「Excel RAND() の振る舞いに似せて、ワークシートを再計算するたびに乱数を自動的に更新する方法」として、乱数の種に Excel VBA の擬似乱数関数 Rnd (ワークシート関数の rand() と混同しないこと) を使えばよいと書いているので本家の NtRand のページの注釈をもとに記述すると以下のようになるはずである。


Dim Result As Variant
Result = Application.Run("NtRandNorm", T, rnd(), rnd())

 が、実際にこれで乱数を何系列も発生させると、同一の乱数を発生させてしまった。これは、NtRandNorm の第3引数・第4引数の定義は長整数型なので rnd() で発生する数値では 0 か 1 としか認識できないのではないか? 実際、rnd() に十分に大きい整数(下の式では N と M)を乗じて新たな種とすると、確かに異なる乱数の列を発生するではないか! できれば N と M はループ変数などと連動して絶えず変化する値であることがのぞましい。


Dim Result As Variant
Result = Application.Run("NtRandNorm", T, N*rnd(), M*rnd())

 ところで、だ。この結果を利用しようとしたとき、たとえば最初から100番目の値をどうやって取得するのかというと、


a =Result(100)

ではなく


a =Result(100,1)

なのだ。それから、最初から Result にはDouble型の変数が入るのはわかりきっているから、また1次元の配列が入るからといって


Dim Result(T) As Double
Result = Application.Run("NtRandNorm", T, N*rnd(), M*rnd())

として実行すると、「型が違います」と言うエラーになるのでご注意を。

 ちなみに筆者の環境(CPU:Celeron 1.4GHz, Memory 192 MB, on WinXP + Excel2000)で、250個の乱数×1万回の生成で約2分。ただしこの結果をファイルに書き出そうとしたらそれだけで30分かかっても終わらないので、まあ、暇な人以外はやらないほうがいいだろう。

Updated : 2003/04/15

Toolbox Logo
Updated : 2003/04/15