References to $RANDOM in subshells all returning identical values

醉酒当歌 提交于 2019-12-10 09:45:13

问题


The following short script prints a random ten-digit binary number:

#!/usr/bin/zsh
point=''
for i in `seq 1 10`
do
    echo $RANDOM >/dev/null
    point=$point`if [ $RANDOM -gt 16383 ]; then echo 0; else echo 1; fi`
done
echo $point

However, if I remove the apparently useless echo $RANDOM >/dev/null line, the script always prints either 1111111111 or 0000000000.

Why?


回答1:


From the man page:

The values of RANDOM form an intentionally-repeatable pseudo-random sequence; subshells that reference RANDOM will result in identical pseudo-random values unless the value of RANDOM is referenced or seeded in the parent shell in between subshell invocations.

The "useless" call to echo provides the reference that allows the subshell induced by the command substitution to produce a different value each time.




回答2:


Subshells (as created by backticks, or their modern replacement $()) execute in a different context from the parent shell -- meaning that when they exit, all process-local state changes -- including the random number generator's state -- are thrown away.

Reading from $RANDOM inside the parent shell updates the RNG's state, which is why the echo $RANDOM >/dev/null has an effect.

That said, don't do that. Do something like this, which has no subshells at all:

point=
for ((i=0; i<10; i++)); do
  point+=$(( (RANDOM > 16383) ? 0 : 1 ))
done

If you test this generating more than 10 digits -- try, say, 1000, or 10000 -- you'll also find that it performs far better than the original did.



来源:https://stackoverflow.com/questions/32577117/references-to-random-in-subshells-all-returning-identical-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!