如何配置 RANDOM 以获取相同的 32 位随机数范围,例如使用 SRANDOM?

Edd*_*763 2 shell bash random

环境:

  • Debian
  • 重击

什么是已知的:

RANDOM 通过以下方式给出一个 15 位范围内的随机数:

echo $RANDOM
Run Code Online (Sandbox Code Playgroud)

SRANDOM 通过以下方式给出 32 位范围内的随机数:

echo $SRANDOM
Run Code Online (Sandbox Code Playgroud)

RANDOM 可以通过以下方式配置为在 30 位范围内创建随机数:

my_rnd=$(((RANDOM<<15|RANDOM)))
echo "$my_rnd"
Run Code Online (Sandbox Code Playgroud)

RANDOM 可以通过以下方式配置为在 45 位范围内创建随机数:

my_rnd=$(((RANDOM<<15|RANDOM)<<15|RANDOM))
echo "$my_rnd"
Run Code Online (Sandbox Code Playgroud)

如何配置RANDOM以获得与使用时相同的 32 位随机数范围SRANDOM

Sté*_*las 5

你可以这样做:

(( my_rnd = (RANDOM << 17) | (RANDOM << 2) | (RANDOM & 3) ))
Run Code Online (Sandbox Code Playgroud)

也就是说,取第一个 RANDOM 的所有 15 位,移位 17 位,另一个 RANDOM 的另外 15 位,移位 2 位,以及第三个 RANDOM 的额外 2 位(较低的,您也可以RANDOM >> 13用于较高的,至少在旧版本bash中明显更加随机)。


ilk*_*chu 5

my_rnd=$(((RANDOM<<15|RANDOM)))
Run Code Online (Sandbox Code Playgroud)

这只是使用RANDOM两次,每次 15 位,第一个值向左移动 15 位。所以你得到一个二进制数aaaaaaaaaaaaaaabbbbbbbbbbbbbbb,其中 a 是代表第一个值的位,b 是代表第二个值的位。

类似地,要获得任意数量的位,您可以使用RANDOMorSRANDOM生成至少那么多位,与 shift ( <<) 和or ( |)一起收集,然后用( &)屏蔽其余部分。例如,对于 32 位,您将使用以下掩码0xffffffff

echo "$(( ((RANDOM<<30) | (RANDOM<<15) | RANDOM) & 0xffffffff ))"
Run Code Online (Sandbox Code Playgroud)

0xffffffff是最大的 32 位二进制值,十进制为 4294967295。您也可以使用((1 << 32) - 1)它来动态计算它。)


请注意,Bash 的手册似乎没有对产生的值的不可预测性做出任何承诺RANDOM,但SRANDOM它说:

SRANDOM
每次引用此变量时,它都会扩展为 32 位伪随机数。随机数生成器在支持/dev/urandom或 的系统上不是线性的arc4random,因此每个返回的数字与其前面的数字没有关系。

这意味着它RANDOM确实可能是一个线性同余生成器,也就是说,不是一个非常好的随机生成器。/dev/urandom并且arc4random用更好的算法实现,所以如果它可用,你应该使用SRANDOM.


即使SRANDOM在您的 Bash 版本中不可用,您的系统也有/dev/urandom可能可用。因此,如果您确实需要比RANDOM提供的更好的随机数,则可以直接使用它。基于Using /dev/random, /dev/urandom to generate random data 中的答案,这将arrn随机 32 位数字填充 shell 数组:

n=10
arr=( $(od -vAn -N $((n*4)) -tu4 < /dev/urandom) )
Run Code Online (Sandbox Code Playgroud)

(故意使用分词,IFS不得包含数字。)

  • 在旧版本的 bash 中,$RANDOM(最初是 ksh 功能)随机性非常糟糕并且几乎不可用。 (2认同)