Rnd、Randomize
乱数の発生にはRnd関数を使います。
Rnd関数は0以上1未満の範囲のSingle型の値を返します。Rnd関数はブックを開きなおす度に同じ乱数値が発生します。
それを防ぐにはRandomizeステートメントを事前に実行して疑似乱数列を初期化します。
疑似乱数列
乱数列は本来であれば次の値が何になるか規則性がないようにすべきですが、コンピュータでの乱数は計算から算出されるためどうしても規則性を持ってしまいます。
規則性があるということは、乱数を基にした暗号などが解読されてしまう恐れもあります。
そのため乱数列が一定にならないようにするために、種(たね)と言われるシード値を使って、シード値に応じた乱数列を疑似的に生成し、規則性をわかりにくくします。
これを疑似乱数列と言います。
ただ、シード値が同じであれば、そのシード値を基にした疑似乱数列は初期化される度に同じになります。これは言い換えれば紙に印刷された乱数表みたいなもので、乱数を発生させる作業に毎回その乱数表を使っていれば規則性は毎回同じになってしまいます。
VBAでの疑似乱数列は対象のブックを閉じるとクリアされるため、シード値が同じであればブックを開きなおすと前回の疑似乱数列での乱数を再度出力します。
なお、Excelアプリケーションは閉じなくてもブックを閉じれば疑似乱数列は初期化されます。
例えば以下のコードはシード値を1にした場合のRnd関数を行う処理ですが、シード値が同じためマクロが書いてあるブックを開きなおして実行するたびに同じ乱数を出力します。
1 2 3 4 5 6 7 8 |
Sub RndTest() Call Randomize(1) Debug.Print Rnd Debug.Print Rnd Debug.Print Rnd Debug.Print Rnd End Sub |
実行結果
1回目、2回目、3回目・・・
0.7648737
0.1054455
0.6134542
0.9377558
この結果のように乱数に再現性があるのは通常はよくないとされるため、再現性を持たせないためにVBAではRandomizeステートメントの引数を省略して、PCのシステム時刻を基にシード値を決定することで疑似乱数列の再現性がないようにしています。
構文
Function Rnd([Number]) As Single
擬似乱数を0以上から1未満の値で返します。
Number | 乱数の発生方法を指定します。
|
||||||||
戻り値 | Single値の乱数値を返します。 |
Sub Randomize([Number])
Rnd関数で使う擬似乱数を再生成します。Randomizeを呼び出すことで次のRnd関数では前回とは異なる乱数が発生するようになります。
Number | 通常は省略します。
指定する場合は疑似乱数列の初期化を行うシード値を指定します。 省略時はPCのシステム時刻を基にしたシード値になります。 |
指定範囲の乱数を取得したい場合
Rnd関数は0以上1未満の範囲の値の単精度浮動小数点数値を返しますが、実際に必要な乱数値は1から10までのような整数の一定の範囲であることの方が多いです。
そのような一定の整数範囲内での乱数が必要な場合は以下のようなコーディングを行います。
Int((最大値 – 最小値 + 1) * Rnd + 最小値)
サイコロのサンプルコード
1から6までのいずれかを乱数として算出するサンプルです。
上記の指定範囲の乱数を取得するための方法を採用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Sub DiceRndSample() Dim iMin '// 最小値 Dim iMax '// 最大値 Dim ret '// 乱数 iMin = 1 iMax = 6 '// 疑似乱数列を初期化 Call Randomize '// 最小値から最大値の範囲の乱数を取得 ret = Int((iMax - iMin + 1) * Rnd + iMin) Debug.Print ret End Sub |