和風スパゲティのレシピ

日本語でコーディングするExcelVBA

Rnd関数で生成される乱数は毎回一緒

知らずに落ちると抜け出せなくなるVBAの落とし穴です。

  • シミュレーターを作ったけど結果が毎回一緒
  • 乱数による分岐が毎回同じCaseに入る

あたりにお悩みの方は、この落とし穴に落ちていないかご確認ください。

Rnd関数の仕様

以下のコードを実行してみてください。

Sub 乱数生成テスト()
    
    Debug.Print Rnd
    
End Sub

「0.7055475」が表示されたんじゃないでしょうか?


いきなり手品師みたいな問いかけから始めましたが、
種も仕掛けもなく、単純にVBAの乱数は固定になっています。


Excelを開いて最初に生成された乱数は「0.7055475」で固定で、
「0.533424」「0.5795186」・・・と続きます。

Excelを閉じるとこの生成がリセットされ、
また↑の羅列が再スタートする仕様になっています。


ExcelVBAでシミュレータなどを作成する場合は、
この仕様に注意してください。

対策 - Randomize/RandBetween

対策は簡単で、マクロの冒頭でRandomizeを実行してください。

Sub 乱数生成テスト()

    Randomize ' ← これを実行
    
    Debug.Print Rnd
    
End Sub

今回の仕様は「乱数のシードが毎回固定」であることに起因しているのですが、
Randomizeを実行するとこのシード値が更新されます。
更新されるシード値はランダムになっていますので、
これで正真正銘のランダムな値を生成してくれるようになります。


また他の対策として、シート関数のRandBetweenを使用しても良いです。

Sub 乱数生成テスト()

    Debug.Print WorksheetFunction.RandBetween(1, 10)
    
End Sub

シート関数で生成する乱数は毎回別シード値で生成されますので、
特にRandomizeなどを実行せずともランダムな値を生成できます。

生成する値が整数でよいなら、こちらを使用するのが簡単ですね。


ちなみにWorksheetFunction.Randは残念ながら実装されていません。

シート関数に「RAND」はありますが、
LEFTやRIGHTと同様、同名同機能の関数がある場合は、
WorksheetFunctionは実装されない模様です。


小数0~1の乱数が欲しい場合は、
素直にRandomizeを実行してください。