生成随机数而不会发生冲突

时间:2017-10-26 00:04:42

标签: bash random

我想在bash中生成不同的随机数。我使用$ RANDOM,但在我的输出中,一些数字是相同的。

var1=$((1+$RANDOM%48))
var2=$((1+$RANDOM%48))
var3=$((1+$RANDOM%48))
var4=$((1+$RANDOM%48))
var5=$((1+$RANDOM%48))
var6=$((1+$RANDOM%48))
它给了我1到48之间的6个数字,但我需要1到48之间的6个不同的数字,事实是我真的很新,我甚至不知道如何开始。

3 个答案:

答案 0 :(得分:7)

如果您想在1-48之间使用6个不同的伪随机数,这是一种实现它的方法

$ seq 48 | shuf | head -6


18
10
17
3
11
6

或直接使用shuf选项(如this answer

shuf -i 1-48 -n 6

另一种方法是拒绝抽样。使用awk

awk 'BEGIN{srand(); 
           do {a[int(1+rand()*48)]} while (length(a)<6); 
           for(k in a) print k}'

8
14
16
23
24
27

这里拒绝是隐含的,再次添加相同的数字不会增加数组大小(实际上是一个哈希映射)

可以将结果赋给变量,但结构需要使用数组,例如

declare -a randarray
readarray randarray < <(seq 48 | shuf | head -6)

您可以使用相应的索引(从0开始)

访问各个元素
echo ${randarray[3]}

一般情况下,如果您的样本数量接近样本空间的范围,您将需要随机播放(极端情况下,如果您想要1-N范围内的N个数字,那么您要求的是随机排列),或者如果比例很小,拒绝抽样可能会更好,(极端情况下你想要一个随机变量)。如果您有其他条件来消除样品,则主要使用拒绝取样。但是,直接使用带有选项的shuf非常快,根本不需要拒绝抽样方法。

答案 1 :(得分:3)

shuf -i 1-48 -n 6

将为您提供1到48之间的6个随机数。默认情况下,所有这些都是不同的。

答案 2 :(得分:0)

此算法将滚动六个随机数并检查每个数字,以确保没有任何重复。

declare -a nums

let times=6

for i in $(eval echo {0..$times}); do
    let nums[$i]=0
    let dup=1
    while [ $dup -eq 1 ]; do
        let temp=$((1+$RANDOM%48))
        let dup=0

        for j in $(eval echo {0..${#nums[*]}}); do
            let cur=$((${nums[$j]}))
            if ! [ "$cur" -eq "$cur" ] 2> /dev/null; then
                break
            fi
            if [ "$cur" -eq "$(eval echo $temp)" ]; then
                let dup=1
            fi
        done
    done

    let nums[$(($j - 1))]=$temp
done

echo ${nums[@]:0}

exit 1