LoginSignup
8
4

More than 5 years have passed since last update.

AWKのrandが同じ乱数列を生成してしまう

Last updated at Posted at 2018-04-22

awk(gawk)には乱数を生成する組み込み関数としてrandが用意されているのですが、たとえば以下のようなソースコードで検証ができるように、実行のたびに同じような乱数列を生成してしまいます。

for _ in $(seq 5); do
  awk 'BEGIN{print(rand(), rand(), rand())}'
done
# 0.237788 0.291066 0.845814
# 0.237788 0.291066 0.845814
# 0.237788 0.291066 0.845814
# 0.237788 0.291066 0.845814
# 0.237788 0.291066 0.845814

awkの仕様なのか、gawkの実装がそうなのか、正直なところよくわからないのですが、乱数生成のシード値の初期値が一定になっているらしく、そのために実行のたびに同じような乱数列が生成されてしまうようです。したがって実行のたびに異なった乱数列を生成したいという場合はsrandを使って、シード値を変更すればよい――と思って書いたのが以下のコードになります。

for _ in $(seq 5); do
  awk 'BEGIN{srand(); print(rand(), rand(), rand())}'
done
# 0.589234 0.904348 0.441211
# 0.589234 0.904348 0.441211
# 0.589234 0.904348 0.441211
# 0.50575 0.499608 0.730847
# 0.50575 0.499608 0.730847

結果から述べると、想定通りに動作しませんでした。確かにsrandがシード値を書き換えてはくれているようですが、まだまだ同じような乱数列を生成してしまう。この原因をいろいろ調べたところ、srandは引数を省略したとき、実行時の時刻をシード値に設定するのですが、この「時刻」の単位が「秒」。つまり1秒以内にsrandを呼び出すと、同じシード値が設定されてしまい、結果として同じ乱数列が生成されてしまいます。

よってsrandの引数は省略せず、自前で用意したシード値を設定する必要がありそうです。そしてそのシード値を自前で用意する方法ですが、awkの外部で生成した乱数を利用することとします。たとえばbashの組み込み変数RANDOMで生成した乱数を-vオプションを使って、awk内部に引き渡し、これをsrandの引数(=乱数のシード値)としたところ、想定通り動作しました(´・ω・`)

for _ in $(seq 5); do
  awk -v seed="${RANDOM}" 'BEGIN{srand(seed); print(rand(), rand(), rand())}' 
done
# 0.975518 0.212486 0.0285477
# 0.838674 0.664669 0.070124
# 0.314944 0.212045 0.00891201
# 0.725379 0.64815 0.805276
# 0.109255 0.713515 0.799796

-vオプションの利用が難しい場合は「外部コマンドで乱数を生成、それをgetlineで拾って、シード値とする」という方法でも大丈夫そうです(´・ω・`)

for _ in $(seq 5); do
  awk 'BEGIN{
    "seq 32767 | shuf -n 1" | getline seed
    srand(seed); 
    print(rand(), rand(), rand())
  }'
done
# 0.711337 0.206352 0.0366282
# 0.614835 0.52362 0.556768
# 0.666671 0.18371 0.66057
# 0.964642 0.860411 0.500877
# 0.95293 0.590551 0.826792

参考 www.kt.rim.or.jp/~kbk/gawk-30/gawk_13.html

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4