【问题标题】:Generate random number except values in bash生成随机数,除了 bash 中的值
【发布时间】:2019-02-06 13:06:14
【问题描述】:

我想在某些值之间生成一个随机数,但某些值除外。

我有这个:

shuf -i 1-9 -n 1

或者这个:

$(( ( RANDOM % 10 )  + 1 ))

但我想排除数字 3 和数字 8,例如。

【问题讨论】:

  • 如果生成3或8,重新生成?

标签: bash shell random


【解决方案1】:

实用通用解决方案

您可以使用-e 选项(至少对于来自GNU coreutils 的shuf)单独指定每个有效数字,而不是指定数字范围,或者您可以在(匿名)文件中指定数字。由于最后一个选项更便携(也适用于 BSD 上的shuffle),我们将使用它。现在我们只需要生成带有数字 1、2、4、5、6、7、9 的输出。以下是一些示例:

shuf -n 1 <(seq 9 | grep -Fxv -e{3,8})

shuf -n 1 <(printf %s\\n 1 2 4 5 6 7 9)

shuf -n 1 <(printf %s\\n 1 2 {4..7} 9)

shuf -n 1 <(seq 2; seq 4 7; echo 9)

只是为了好玩

对于每个有限集 S={i1,i2,…in}⊂ℕ 的整数,您可以得出 (手动)与多项式 f 使得 f(x)=ix 对于所有 x∈{0,1,…,n-1}。

一般来说,多项式 f 的次数为 n-1。有时我们可以使用四舍五入来降低度数。在 S={1,2,4,5,6,7,9} 的具体情况下,我们可以使用 f(x) = floor(1.25x+1.5)。这是bash 中使用bc 的实现((…) / 1 向下舍入)。

bc <<< "($RANDOM % 7 * 1.25 + 1.5) / 1"

这种方法的一个好处是,如果我们将公式中的所有数字缩放为整数(这里我们缩放了 4 倍),它可以与内置函数一起使用。

echo $(( ($RANDOM % 7 * 5 + 6) / 4 ))

【讨论】:

    【解决方案2】:

    这是一种方法:

    until N=$(( ( RANDOM % 10 )  + 1 )); (( $N != 3 && $N != 8 )); do true; done; echo $N
    

    有人可能会争辩说这种方式效率不高,但在没有明显、简单的替代方案的情况下,它应该适合。

    【讨论】:

      【解决方案3】:

      一个函数?

      rnd() {
        local n=$(( $RANDOM % 10 ))
        while [[ $n =~ [038] ]]
        do n=$(( $RANDOM % 10 ))
        done
        echo $n
      }
      

      那你可以直接说x=$( rnd )

      【讨论】:

      • 循环会比递归函数好得多。
      • 是的。会修复。只是在工作任务之间玩得开心,哈哈
      【解决方案4】:

      从任何一组值中选择一个随机值的简单方法是将这些值放入一个数组中,然后从数组中选择一个随机项。在这种情况下:

      values=(1 2 {4..7} 9)
      random_value=${values[RANDOM % ${#values[*]}]}
      

      另见Select a random item from an array

      上面的代码有一些限制。首先,如果要从中选择的值的数量大于 32768,则它不起作用,因为$RANDOM 的最大值是 32767。(对于大于该值的数字,数组的大小可能会成为问题。)其次,RANDOM % ${#values[*]} 返回的值(通常略微)偏向较低的数组索引。有关更多信息,请参阅Why do people say there is modulo bias when using a random number generator?。如果这对您很重要,请参阅 BashFAQ/026 (How can I randomize/shuffle the order of lines in a file? ...) 中的 rand 函数,了解在有限范围内生成无偏(伪)随机数的 Bash 代码。

      【讨论】:

        猜你喜欢
        • 2017-05-02
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 2013-02-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多