linux shell中范围之间的随机数

aiazj4mn  于 2023-04-05  发布在  Linux
关注(0)|答案(7)|浏览(217)

如何在sh(/bin/sh,不是bash)中生成0-60之间的随机数?这是一个卫星盒,没有$RANDOM变量,其他商品[cksum,od(od -货车-N4 -tu 4〈/dev/urandom)]。
我想随机化一个crontab作业的时间。

ql3eal8s

ql3eal8s1#

如果你有tr、head和/dev/urandom,你可以这样写:

tr -cd 0-9 </dev/urandom | head -c 3

然后你必须使用余数运算符把0-60的范围。

iklwldmw

iklwldmw2#

如何使用系统时间的纳秒?

date +%N

这里不需要密码学上有用的数字。
根据/bin/sh的版本,您可以执行以下操作:
$((date +%N % 60))
如果它不支持$(())语法,但你有dc,你可以尝试:

dc -e `date +%N`' 60 % p'

如果不知道哪个操作系统、/bin/sh的版本或可用的工具,很难提出保证有效的解决方案。

xj3cbfub

xj3cbfub3#

我知道这篇文章已经很老了,但建议的答案并不是产生均匀无偏的随机数。公认的答案基本上是这样的:

% echo $(( $(tr -cd 0-9 </dev/urandom | head -c 3) % 60))

这个建议的问题是,通过从/dev/urandom中选择一个3位数,范围是从0到999,总共1,000个数字。然而,1,000不能平均分为60。因此,您将偏向于生成0-959,而不是960-999。
第二个答案,虽然创造性地使用了你的时钟的纳秒,但也有同样的偏见:

% echo $(( $(date +%N) % 60 ))

纳秒的范围是0- 999,999,999,这是10亿个数字。因此,如果将结果除以60,您将再次偏向于生成0- 999,999,959略高于999,999,960 - 999,999,999。
所有其余的答案都是相同的--有偏见的非均匀生成。
要生成0-59范围内的无偏均匀随机数(我假设他的意思是0-60,如果他试图随机化crontab(1)条目),我们需要强制输出为60的倍数。
首先,我们将生成一个介于0和4294967295之间的随机32位数:

% RNUM=$(od -An -N4 -tu2 /dev/urandom | awk '{print $1}')

现在我们将强制我们的范围在$MIN和4294967295之间,这是60的倍数:

% MIN=$((2**32 % 60)) # 16

这意味着:

4294967296 - 16 = 4294967280
4294967280 / 60 = 71582788.0

换句话说,我的区间[16,4294967295]正好是60的倍数。因此,我在该区间生成的每个数字,然后除以60,将与任何其他数字一样可能。因此,我有一个无偏的数字生成器0-59(或1-60,如果你加1)。
剩下唯一要做的就是确保我的号码在16和4294967295之间。如果我的号码小于16,那么我需要生成一个新号码:

% while [ $RNUM -lt $MIN ]; do RNUM=$(od -An -N1 -tu2 /dev/urandom); done
% MINUTE=$(($RNUM % 60))

一切放在一起复制/粘贴goodnees:

#!/bin/bash
RNUM=$(od -An -N4 -tu2 /dev/urandom | awk '{print $1}')
MIN=$((2**32 % 60))
while [ $RNUM -lt $MIN ]; do RNUM=$(od -An -N1 -tu2 /dev/urandom); done
MINUTE=$(($RNUM % 60))
watbbzwu

watbbzwu4#

你有awk吗?你可以调用awk的兰德()函数。例如:

awk 'BEGIN { printf("%d\n",rand()*60)  }' < /dev/null
bqjvbblv

bqjvbblv5#

value=`od -An -N2 -tu2 /dev/urandom`
minutes=`expr $value % 60`

种子将在0和65535之间,这不是60的偶数倍,因此分钟0-15具有稍大的机会ob被选择,但是差异可能并不重要。
如果你想达到完美,使用“od -An -N1 -tu 1”并循环直到值小于240。
使用busybox od测试。

rseugnpd

rseugnpd6#

当生成的数字从0开始并且有大于7的其他数字时,请注意错误,因为它被解释为八进制,我建议:

tr -cd 0-9 </dev/urandom | head -c 4 | sed -e 's/^00*//

特别是如果你想进一步处理它,例如建立一个范围:

RANDOM=`tr -cd 0-9 </dev/urandom | head -c 4 | sed -e 's/^00*//'`
RND50=$((($RANDOM%50)+1))   // random number between 1 and 50
v2g6jxz6

v2g6jxz67#

经过一年的使用投票最高的解决方案,从这个线程,在Shell中生成一个范围之间的随机数,我已经证实,正如@Aaron Toponce所建议的那样,这种方法是有偏差的,不是均匀随机的。在范围1-65535中,以下数字随机生成不超过一次(在一年内):3、4、6、7、9、13、17、19、20、21、58080、60020、60443、61532、61900、62078、63331、64623、64680、65000、65129、65389。请注意,这些数字是范围的钟形曲线上的统计异常值。相反,同样的方法有一种趋势,即在钟形曲线内“随机”生成公共数字,其中某些频率被证明对于生产实施是不可靠的。同时,仍然在寻找一个纯Shell解决方案,该解决方案生成一个范围之间的随机数,这不需要替代应用程序。

相关问题