乱数の発生

CindyScriptで乱数を発生する方法について考えます。

乱数の発生に関係する関数は、CindyScriptに次の6つが用意されています。

random() : 引数なし 0から1までの一様乱数を発生

randomnormal() : 引数なし (0,1)正規乱数を発生。正規乱数とは、発生した乱数の分布が正規分布に従うもの。

randombool() : 引数なし true または false を発生

random(数) : 0から引数までの実数の一様乱数

randomint(数):0から引数までの整数の一様乱数

seedrandom(数) : 引数に与えた数に対して、実行するたびに同じ乱数列が発生

ここでは、「1,2,3のどれかが同じ確率で出現する乱数」を発生させてみましょう。整数値が欲しいので、randomint()を使います。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

n1=0;

n2=0;

n3=0;

repeat(100,

   a=randomint(3)+1;

   if(a==1,n1=n1+1);

   if(a==2,n2=n2+1);

   if(a==3,n3=n3+1);

);

println(n1+","+n2+","+n3);

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

n1,n2,n3 はカウンタです。1,2,3の数が何回現れたかを数えます。最初は0です。

5行目で1,2,3のいずれかの数を発生します。randomint(3)は0から3までの整数の一様乱数を発生しますが、「3まで」がちょっとくせ者で、式で書くと 0≦x<3 なのです。3はできません。すなわち実際にできるのは0,1,2の3通りなのです。そこで、1を加えて1,2,3のどれかになるようにしています。

そのあと、発生した乱数aが1か2か3かによって、カウンタn1,n2,n3の値を1つ増やします。

これを100回繰り返して、最後にコンソールに表示します。

うまくいっているように見えますが、実際には実行するたびにかなりばらつきが出ます。とはいえ、これはしかたのないことです。1000回、10000回と回数を増やせば確率3分の1に近くなります。これは「一様乱数」のもともとの性質です。

これで「確率3分の1で数「1」を発生する」というコードが書けます。

目的は達成できましたが、CindyScriptでちょっと遊んでみましょう。

上のスクリプトでは、発生した乱数を変数aに代入し、その値を if で判断してカウンタを動かしています。これに対し、「リスト」を使えば if による判定がいらなくなるのです。

リストは、「ものを集めたもの」です。3つの数のリストは [2,4,6] のように表現されます。2と4と6からなるリストです。ここで、n1,n2,n3 というカウンタをリストにするのです。[n1,n2,n3]です。最初は全部0なので [0,0,0]です。

さて、乱数aができたら、それが整数で1,2,3のいずれかであることを利用します。どういうことかというと、1,2,3という数はそのまま「番号」として使えるからです。たとえば、1がでたらそれは1番目ということにします。そこで、リストの1番目の要素に1を足します。すこし具体的に例をあげてみましょう。

最初は何もない [0,0,0]

乱数1が出た [1,0,0]

また1が出た [2,0,0]

次に3が出た [2,0,1]

さて、リストのn番目の要素は _n で指定できます。_はアンダーバーです。すると、次のスクリプトで先ほどと同じことができます。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

n=[0,0,0];

repeat(100,

   a=randomint(3)+1;

   n_a=n_a+1;

);

println(n);

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー