问题
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