シェルの乱数

シェルで乱数を生成したいときがある.

たとえば 乱数生成のseedを乱数で与えたいときなんかに有効だ.
たくさんのjobを投げるときにseedを時間で与えるとすべてのjobの乱数列が同じになってしまう.
こんなときにseedを乱数にするとjobひとつひとつで違う乱数列を生成できるのだ.

シェルで乱数を発生させるコマンドは

echo $RANDOM

あるいは

od -vAn -N4 -tu4 < /dev/random

だ.

このふたつのコマンドで出力される乱数はどんな分布になっているのだろう.
それを調べてみたい.

echo $RANDOM

$RANDOMはbashzshに用意されている変数です.
man bash あるいは man zshparam を調べると 0 から 32767 までの整数が格納されるようだ.
つぎのようなスクリプトを書いて$RANDOMに格納されている乱数をテキストファイルに出力する.

touch random_env.txt
for i in {1..10000}
do
	echo $RANDOM >> random_env.txt
done

この出力された乱数を numpy とmatplotlib で統計処理してみる.

import numpy as np
import matplotlib.pyplot as plt
import sys

filename = sys.argv[1]
data = np.loadtxt(filename)

plt.hist(data, bins = 50)
plt.show()

得られたヒストグラムを示す.
f:id:konnyakmannan:20130206082846p:plain
ほぼ一様分布になっている.
マニュアルのとおり 0 から 32767 までの整数が生成されているようだ.

od -vAn -N4 -tu4 < /dev/random

od コマンドはファイル/dev/randomの中を8/10/16進数で表示する.
この場合 オプションによって10進数で表示するようになっている.
先程と同様にテキストファイルに乱数を出力する.

touch random_cmd.txt
for i in {1..10000}
do
	od -vAn -N4 -tu4 < /dev/random >> random_cmd.txt
done

こっちは$RANDOM変数に比べてだいぶ時間がかかる.
こちらも numpy と matplotlib を使って処理する.
f:id:konnyakmannan:20130206084000p:plain
こちらも一様分布になっている.
ただ出力する整数の範囲が広い.

まとめ

$RANDOM変数を使うと0 から 32767 までの一様乱数が得られる.

一方で od コマンド使うと範囲の広い,一様に分布した乱数が得られる.
しかし od コマンドを使うと時間がかかることがわかった.

計算時間が気になるときは$RANDOM変数を使うのが良いだろうか.

乱数のseedにするならば$RANDOMから得られた乱数と時間の演算(和か積かな?)がいいだろう.