Unix $ RANDOM函数在Bash终端中不是随机的

时间:2013-09-07 22:51:04

标签: bash unix terminal

我正在尝试使用bash终端中的$ RANDOM函数在指定范围之间生成一个随机数。问题是它产生的数字似乎根本不是随机的。我使用的脚本是:

RANDOM=$$;

a=$RANDOM
b=9; #Number of scripts in collection -1
c=`expr $a % $b `; #Random number between 0 and b

if (( c==0 ));
then

echo "script 1 (random = $a, mod = $c)";

elif (( c==1 ));
then

echo "stript 2 (random = $a, mod = $c)";

...

else

echo "error (random = $a, mod = $c)";

fi;

如果我在for循环中运行它,我会得到,例如:

script 8 (random = 17845, mod = 7)
script 8 (random = 18754, mod = 7)
script 8 (random = 19663, mod = 7)
script 7 (random = 20571, mod = 6)
script 7 (random = 21480, mod = 6)
script 6 (random = 22388, mod = 5)
script 6 (random = 23297, mod = 5)
script 6 (random = 24206, mod = 5)
script 5 (random = 25114, mod = 4)
script 5 (random = 26023, mod = 4)

这显然不是随机的。

我尝试删除$ a并运行

c=`expr $RANDOM % $b`; 

然后将代码更改为另一个变体

c=`expr $a \* $b \/ 32767`;

但这些(不出所料)返回了相同的结果。我究竟做错了什么?或者这对$ RANDOM来说只是一个有点刺激性的限制?任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:2)

你一直用相同的号码播种RANDOM。尽量不要播种或使用更随机的项目播种:

RANDOM=$$

显然$$不会一直改变,因为它始终是shell的主PID(不是子shell PID)。如果你实际上正在调用不同的shell,那么可能没有太大区别,因为每个PID增加的数字仅增加1。所以要么你可以删除它,要么在/dev/urandom等地方获得另一个随机种子

通过/dev/urandom应用随机种子的一种好方法:

RANDOM=$(tr -dc 0-9 < /dev/urandom | head -c10)

另一个纳秒(播种数量大于这些似乎没有产生良好效果):

RANDOM=$(date '+%N')

另外,为了使它在不同的子流程中看起来更独特,请将BASHPID(优于$$)添加到种子中:

RANDOM=$(( BASHPID + $(date '+%N') ))

答案 1 :(得分:2)

我认为可以找到解释here

  

当您使用模数运算时,您正在从中选择信息   一个数字的低位和从中丢弃的信息   高阶位... X的最低有效(右手)数字   不是很随机,所以基于数字X的决定应该始终如此   主要受最重要数字的影响。

使用这个 对我来说效果更好(虽然我只测了几次):

c=$(($a * $b / 32768))

这是经过修改的脚本:

#!/bin/bash

RANDOM=$$;
a=$RANDOM

b=9; #Number of scripts in collection -1

c=$(($a * $b / 32768))

if (( c==0 )); then
    echo "script 1 (random = $a, mod = $c)";
elif (( c==1 )); then
    echo "script 2 (random = $a, mod = $c)";
else
    echo "error (random = $a, mod = $c)";
fi;

希望这有帮助。