【问题标题】:how to generate equal number of two values in bash如何在bash中生成相等数量的两个值
【发布时间】:2016-08-27 14:20:09
【问题描述】:

我需要在 bash 中随机生成一系列“a”和“-a”。我必须有相同数量的“a”和“-a”,这意味着数组的总和应该为零。类似的东西:

n=20;
for i in seq 1 1 n
do
    if test $RANDOM -ge 16378
    then
        a=1
    else
        a=-1
    fi
done

与此类似的东西会随机生成“a”和“-a”,但总和并不总是为零。我应该如何在代码中应用这个条件?!

感谢

【问题讨论】:

  • 如果它是可预测的,它就不是真的随机。
  • 你的情况不会再随机化了。
  • 你是想说对于an个数,-a应该有n个数,所以总和是零,但它们应该“随机”排序?
  • 仅仅因为样本空间是结构化的(在这种情况下,零和的值序列)并不意味着您不能从空间中随机选择一个元素。
  • 随机性只是按照数字的顺序,例如:[a a -a a -a -a -a a a -a ...]。 @詹斯

标签: arrays bash if-statement


【解决方案1】:

我添加了一个单独的答案,因为您实际上可能正在寻找更简单的东西。如果你想循环遍历 20 个值,其中 10 个是 1,其中 10 个是 -1,按随机顺序,我会这样做:

$ for i in {1..10}; do echo 1; echo -1; done | shuf
-1
1
-1
1
-1
1
-1
1
1
1
-1
1
-1
-1
-1
-1
1
1
1
-1

【讨论】:

  • 我喜欢这个答案。简单,而且似乎符合要求。
  • 确实如此。谢谢
【解决方案2】:

我将您的问题解释为等同于创建一个已知长度的数组,其中包含一定数量的a 和相同数量的-a,然后得到该数组的随机排列。

您需要在bash 中进行吗?如果是这样,您可以先创建所需长度的数组,然后对其进行随机播放。

来自BashFaq

此函数使用 Knuth-Fisher-Yates 洗牌算法就地洗牌数组的元素。

#!/bin/bash

shuffle() {
   local i tmp size max rand

   # $RANDOM % (i+1) is biased because of the limited range of $RANDOM
   # Compensate by using a range which is a multiple of the array size.
   size=${#array[*]}
   max=$(( 32768 / size * size ))

   for ((i=size-1; i>0; i--)); do
      while (( (rand=$RANDOM) >= max )); do :; done
      rand=$(( rand % (i+1) ))
      tmp=${array[i]} array[i]=${array[rand]} array[rand]=$tmp
   done
}

(复制自Simple method to shuffle the elements of an array in BASH shell?

如果您不限于bash,您可以只使用shuffor 循环到do it as a one-liner

【讨论】:

  • 感谢您的回答,我必须使用 bash 否则我可以在 python 或 matlab 中执行此操作,我不擅长 bash!我会试试这个,让我们看看我得到了什么!如果我有问题,我会回来的。 :)
  • 所以你在上面的代码中说的是我必须先生成数组然后重新排列它。我的问题更多是关于如何生成具有相等数量“a”和“-a”值的数组。假设数组的长度为 n=20,我希望其中 10 个等于“a”,另外 10 个等于“-a”。但我也希望它们像 [a a -a -a -a a -a a a -a ...] 一样随机分布。我不确定我是否足够清楚?! ://
  • 先按已知顺序生成它们,然后改组它们有什么问题。这不是一样的结果吗?
  • 应该是一样的。问题是我将其用作另一个“for”循环中较大代码的一部分。所以如果我一次做所有事情会更容易,否则这也会起作用!也许我只是懒惰!!!! :p 还是谢谢。
  • 如果您想使用特定的算法,我们或许可以帮助您实现它。如果我建议的那个对您的问题没有好处,那么您的问题可能更多是关于算法而不是关于 bash。所以让我问你这个问题:如果你可以在 Python 或 MATLAB 中完成,你会在那里使用什么算法?你可以在那里做的任何事情都可以转换回 bash。可能你想了这个问题之后,会发现你更喜欢我推荐的算法。
【解决方案3】:

很简单,你只需要学会更好地使用 RANDOM。

要获得一个范围内的随机数,然后按范围的长度对其进行修改。在这种情况下,它是二进制的,所以 $((RANDOM % 2))

declare -i total=0     # you need to define this as an integer for += later
for i in {1..20}; do
   declare -i num=$((RANDOM % 2))  # define an integer var
   [ $num -lt 1 ] && ((--num))     # if it's zero, change to -1
   echo $num      # see the number picked
   total+=$num
done
echo "total = $total"

我假设您想查看结果。如果你想对它求和,那么我们会在循环外声明一个变量,然后使用它。我会编辑它。

【讨论】:

  • @SainHax 比你的答案。这与我所拥有的类似,但总和不为零。也许我需要更清楚。在上面的代码中,在这些“20”值中,我需要其中 10 个为“1”,另外 10 个为“-1”。
  • @Elin 是的,你并不清楚——你的最后一段似乎仍然是你想要的。我会编辑。
【解决方案4】:

这可能是你想要的。它产生一个随机数的 'a's 和 '-a's 组合,每个数字的一​​半,使字符串中的 'a's 的数量等于字符串中的 '-a's 的数量。如果我误解了这个问题,请告诉我。 可以限制字符串的最大长度,如果需要请告诉我

# l represents half the length of the array
l=1; # Sets l to 1, set the following while statement evaluates true
# Sets l to $RANDOM until it is an even number 
while [ $((l % 2)) -ne 0 ]; do 
    l=$RANDOM; 
done;
echo $l;
# Sets m and n to l
n=$l; # n is the number of 'a's 
m=$l; # m is the number of '-a's
# Initialises result as an empty string
result="";
# Doesn't stop until both 'a's and '-a's have been exhausted, i.e. n and m both equal 0
while [ "$n" != "0" ] && [ "$m" != "0" ]; do
    # Decides between 'a' and '-a'
    i=$(($RANDOM % 2));
    # Evaluates true if $i is 0, and the number of '-a's has not been exhausted, however also evaluates true if the number of '-a's has been exhausted
    if ([ "$i" == "0" ] && [ "$n" != "0" ]) || [ "$m" == "0" ]; then
        # Appends 'a' to result
        result="$result a";
        # Decrement the amount of 'a's left
        n=$((n-1));
    # Evaluates true if $i is 1, and the number of 'a's has not been exhausted, however also evaluates true if the number of 'a's has been exhausted
    elif ([ "$i" == "1" ] && [ "$m" != "0" ]) || [ "$n" == "0" ]; then
        # Appends '-a' to result
        result="$result -a";
        # Decrements the amount of '-a's left
        m=$((m-1));
    fi; 
done;
# Prints the result
echo $result;

编辑:根据 SaintHax 的建议,已添加代码注释

【讨论】:

  • 为什么 l 是随机的,而不是传递的值?此外,此代码中没有 cmets,您使用的是变量名 l、n、m 吗?应该避免这种情况。如果在 m 或 n 达到零时有一个默认操作,它会快得多。
  • @SaintHax 对不起,我的代码不够清晰,我会尽快添加 cmets,但请记住,我是 15 岁,没有接受过正式的编程培训。我只是想帮忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 2021-04-29
  • 2021-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多