バッチの%RANDOM%は全然ランダムじゃないという罠

バッチファイル(・コマンドプロンプト)で乱数として使えると思っていた環境変数 %RANDOM% を使って罠にハマったというお話。

特別な環境変数 %RANDOM% には 0~32767 までの値のうちどれかが名目上ランダムに入っていることになっている。

で、実際には状況によっては全くランダムじゃなくなるので要注意。

乱数のシードは秒単位

バッチファイルを起動した時刻が秒単位で同じである場合、(乱数のシードがたかだか1秒単位なので)全く同じ乱数が生成する

2つのバッチファイルを同時に開けば、その2つのバッチで %RANDOM% に入っている整数は全く同じになる

例えばバッチから生成した一時ファイルの名前のかぶり対策のために %RANDOM% をファイル名に含めたとしても、同時に起動したバッチなら結局同じになってしまうので要注意。

(かぶり対策なら %RANDOM% ではなくミリ秒単位の時刻を取得してそれを一時ファイル名に入れた方が良い)

近い時刻に取得した %RANDOM% の初期値は近い値になる

全く乱数感が無い。例えば以下のコードのバッチファイルを適当に連続で5回起動してみる。

@echo off
echo %RANDOM%
pause

5回起動した結果はこちら。

バッチ(コマンドプロンプト)で環境変数%RANDOM%がランダムにならず、同じ値になるなどする

1回目と2回目は同じ時刻(秒)での起動のため乱数は同じ29773になった。

2回目~5回目は値こそ変わっているものの、どれも29700番台で明らかに単純に増えているだけ。

適当な整数で割った余りなどを使わないと偏りがとんでもないことになる。

(適当な整数で割ったところでどれだけランダムな疑似乱数なのか…だいぶ怪しい)

まともな疑似乱数としては使えないので要注意。

より詳しい情報

リンク:As random as I wanna be: Why cmd.exe's %RANDOM% isn't so random - The Old New Thing

バッチの罠 一覧

バッチ製作途中で今回のこれ以外も無数にバッチの罠にハマりまくったので、こちらに自分がはまった仕様上の落とし穴をまとめた。

バッチの罠

特定のPowerShellスクリプトを呼び出して実行するバッチファイルを作成していた時にハマった落とし穴をメモ。 [sitecard subtitle=バッチ生成ツール url=https://pajoca.com/ps1-batch-g[…]

記事化前の最新情報はこちらで先にツイートしています。サイト更新告知もこちら。