1

I'm trying to generate a random number in between a specified range by using the $RANDOM function in the bash terminal. The problem is that the numbers it is generating don't appear to be random at all. The script I am using is:

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;

If I run this in a for in loop I get, for example:

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)

Which clearly isn't random.

I tried removing the $a and just running

c=`expr $RANDOM % $b`; 

and then altering the code to another variation

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

But these (unsurprisingly) returned the same result. What am I doing wrong? Or is this just a slightly irritating limitation for $RANDOM? Any advice would be greatly appreciated.

4

2 回答 2

3

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

RANDOM=$$

显然$$并不总是改变,因为它始终是您外壳的主 PID(不是子外壳 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') ))
于 2013-09-07T22:57:58.503 回答
2

我认为可以在这里找到解释:

当您使用取模运算时,您是从数字的低位选择信息并从高位丢弃信息... 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;

希望这可以帮助。

于 2013-09-07T23:03:23.007 回答