Unix外壳-为什么相同的$RANDOM数字重复



我在Unix shell中试用$RANDOM变量,发现了一些奇怪的东西。我运行了以下命令,它在循环中读取$RANDOM 100k次,然后将输出管道传输到";uniq";以查找重复项。

$ for i in {1..100000}; do echo $RANDOM; done | uniq -d

我运行了7次以上的命令,同样的两个数字(4455和4117(重复了7次。下面的屏幕截图显示了命令行输出。

kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117
kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117
kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117
kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117
kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117
kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117
kali@kali:~% for i in {1..100000}; do echo $RANDOM; done | uniq -d
4455
4117

请参阅:https://i.stack.imgur.com/5bpEe.png

我还打开了另一个终端窗口,重复了这个过程。在第二个终端,数字不同,但以类似的方式重复。这让我想知道$RANDOM变量的熵是什么时候产生的,以及它是如何被播种的。

我的猜测是,每当调用bash时,它都会被重新播种,但我想知道是否有人知道当我在单个终端窗口中重复命令时,为什么会重复相同的值。

这是由于一个zsh错误/"行为;在潜艇中为随机数。这个bug没有出现在bash中。

echo $RANDOM # changes at every run  
echo `echo $RANDOM` # always return the same value until you call the first line

因为RANDOM是按其最后一个值进行种子设定的,但在子shell中,所获得的值不会在主shell中更新。

man zshparam:中

RANDOM <S>
A  pseudo-random  integer  from 0 to 32767, newly generated each
time this parameter is referenced.  The random number  generator
can be seeded by assigning a numeric value to RANDOM.
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.

更疯狂的是,调用uniq会创建一个子shell

for i in {1..10}; do echo $RANDOM; done # changes at every run 
for i in {1..10}; do echo $RANDOM; done | uniq # always the same 10 numbers

来源:Debian错误报告828180

随机数生成器并不完美。Lehmer随机数生成器用在bash源中;标准";常数:

x(n+1) = 16807 * x(n) mod (2**31 - 1)

此外,bash将输出限制为仅15位:

#  define BASH_RAND_MAX 32767
...
return ((unsigned int)(rseed & BASH_RAND_MAX));

有了外壳的种子,数字44554117就会相继出现在10000个随机数的连续输出中。真的没什么奇怪的。你可以计算种子,得到两个连续的数字,知道:

# We know that lower 15 bits of previous number are equal to 4455
x(n) mod 32768 = 4455
# We know that lower 15 bits of previous number are equal to 4455
x(n+1) mod 32768 = 4455
# We know the relation between next and previous number
x(n+1) = 16807 * x(n) mod (2**31 - 1)
# You could find x(n)

为什么相同的$RANDOM数字重复?

因为在shell中具有当前种子的bash源中使用的伪随机生成器方法恰好重复相同的数字。

最新更新