如何在Bash中生成一个范围内的随机数?
当前回答
是什么:
perl -e 'print int rand 10, "\n"; '
其他回答
也许我说得有点晚了,但是在Bash中使用jot生成一个范围内的随机数怎么样?
jot -r -p 3 1 0 1
这将生成一个随机的(-r)数字,具有3位小数点后精度(-p)。在本例中,您将得到0到1(1 0 1)之间的一个数字。您还可以打印顺序数据。根据手册,随机数的来源为:
当没有指定种子时,通过arc4random(3)获得随机数,通过 随机(3)当一个种子给出。
试试你的shell:
$ od -A n -t d -N 1 /dev/urandom
这里,-t d指定输出格式应该是带符号的十进制;-N 1表示从/dev/ urrandom读取一个字节。
这是我写的一个函数,它将输出一个期望范围>的随机数
描述:
随机<min> <max> 生成一个从最小到最大的随机数。最小值和最大值都可以 正数或负数,生成的随机数也可以是负数,所以 只要范围(max - min + 1)小于或等于32767。Max必须是>= min。
它的核心是:
random() {
min="$1"
max="$2"
range=$((max - min + 1))
rand=$((min + (RANDOM % range)))
echo "$rand"
}
用法:
# general form: obtain a random number between min and max, inclusive
random <min> <max>
# Example: obtain a random number from -10 to 10, inclusive
random -10 10
这是从bash内置变量RANDOM中工作的,它可能只在底层使用C rand(),因为它们的最大值都是32767——请参阅:
https://en.cppreference.com/w/c/numeric/random/rand https://en.cppreference.com/w/c/numeric/random/RAND_MAX
有关bash文档,请参阅man bash:
随机 每次引用此参数时,都会生成一个0到32767之间的随机整数。随机数序列可以通过赋值给random来初始化。如果RANDOM未被设置,它将失去其特殊属性,即使随后被重置。
健壮的、可运行的、可源代码的脚本版本
这是上面随机函数的一个更健壮的版本。它包括完整的错误检查,边界检查,通过random——help或random -h提供的帮助菜单,以及一个特殊的run_check功能,允许您源或运行此脚本,以便您可以源它以将随机函数导入任何其他脚本——就像您在Python中所做的一样!
random.sh <——点击这个链接总是从我的eRCaGuy_dotfiles repo中获得最新版本。
RETURN_CODE_SUCCESS=0
RETURN_CODE_ERROR=1
HELP_STR="\
Generate a random integer number according to the usage styles below.
USAGE STYLES:
'random'
Generate a random number from 0 to 32767, inclusive (same as bash variable 'RANDOM').
'random <max>'
Generate a random number from 0 to 'max', inclusive.
'random <min> <max>'
Generate a random number from 'min' to 'max', inclusive. Both 'min' and 'max' can be
positive OR negative numbers, and the generated random number can be negative too, so
long as the range (max - min + 1) is less than or equal to 32767. Max must be >= min.
This file is part of eRCaGuy_dotfiles: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles
"
print_help() {
echo "$HELP_STR" | less -RFX
}
# Get a random number according to the usage styles above.
# See also `utils_rand()` in utilities.c:
# https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/c/utilities.c#L176
random() {
# PARSE ARGUMENTS
# help menu
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
print_help
exit $RETURN_CODE_SUCCESS
fi
# 'random'
if [ $# -eq 0 ]; then
min=0
max="none"
# 'random max'
elif [ $# -eq 1 ]; then
min=0
max="$1"
# 'random min max'
elif [ $# -eq 2 ]; then
min="$1"
max="$2"
else
echo "ERROR: too many arguments."
exit "$RETURN_CODE_ERROR"
fi
# CHECK FOR ERRORS
if [ "$max" = "none" ]; then
rand="$RANDOM"
echo "$rand"
exit "$RETURN_CODE_SUCCESS"
fi
if [ "$max" -lt "$min" ]; then
echo "ERROR: max ($max) < min ($min). Max must be >= min."
exit "$RETURN_CODE_ERROR"
fi
# CALCULATE THE RANDOM NUMBER
# See `man bash` and search for `RANDOM`. This is a limitation of that value.
RAND_MAX=32767
range=$((max - min + 1))
if [ "$range" -gt "$RAND_MAX" ]; then
echo "ERROR: the range (max - min + 1) is too large. Max allowed = $RAND_MAX, but actual" \
"range = ($max - $min + 1) = $range."
exit "$RETURN_CODE_ERROR"
fi
# NB: `RANDOM` is a bash built-in variable. See `man bash`, and also here:
# https://stackoverflow.com/a/1195035/4561887
rand=$((min + (RANDOM % range)))
echo "$rand"
}
# Set the global variable `run` to "true" if the script is being **executed** (not sourced) and
# `main` should run, and set `run` to "false" otherwise. One might source this script but intend
# NOT to run it if they wanted to import functions from the script.
# See:
# 1. *****https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/argument_parsing__3_advanced__gen_prog_template.sh
# 1. my answer: https://stackoverflow.com/a/70662049/4561887
# 1. https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/bash/check_if_sourced_or_executed.sh
run_check() {
# This is akin to `if __name__ == "__main__":` in Python.
if [ "${FUNCNAME[-1]}" == "main" ]; then
# This script is being EXECUTED, not sourced
run="true"
fi
}
# ----------------------------------------------------------------------------------------------------------------------
# Main program entry point
# ----------------------------------------------------------------------------------------------------------------------
# Only run main function if this file is being executed, NOT sourced.
run="false"
run_check
if [ "$run" == "true" ]; then
random "$@"
fi
不需要其他依赖项:
$(((RANDOM % $((upperBound - lowerBound))) + lowerBound))
随机数范围为[lowerBound,upperBound)
我已经采取了一些这些想法,并做出了一个函数,应该执行迅速,如果大量的随机数是必需的。
如果你需要很多随机数,调用od的代价是很高的。相反,我只调用它一次,并存储来自/dev/urandom的1024个随机数。当调用rand时,返回最后一个随机数并按比例缩放。然后从缓存中删除它。当缓存为空时,再读取1024个随机数。
例子:
rand 10; echo $RET
返回RET中0到9(含9)之间的随机数。
declare -ia RANDCACHE
declare -i RET RAWRAND=$(( (1<<32)-1 ))
function rand(){ # pick a random number from 0 to N-1. Max N is 2^32
local -i N=$1
[[ ${#RANDCACHE[*]} -eq 0 ]] && { RANDCACHE=( $(od -An -tu4 -N1024 /dev/urandom) ); } # refill cache
RET=$(( (RANDCACHE[-1]*N+1)/RAWRAND )) # pull last random number and scale
unset RANDCACHE[${#RANDCACHE[*]}-1] # pop read random number
};
# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.
declare -i c; declare -ia BIN
for (( c=0; c<100000; c++ )); do
rand 10
BIN[RET]+=1 # add to bin to check distribution
done
for (( c=0; c<10; c++ )); do
printf "%d %d\n" $c ${BIN[c]}
done
更新:这并不适用于所有n。如果使用小n,也会浪费随机比特。注意(在这种情况下)一个32位随机数有足够的熵容纳9个0到9之间的随机数(10*9=1,000,000,000 <= 2*32),我们可以从每个32个随机源值中提取多个随机数。
#!/bin/bash
declare -ia RCACHE
declare -i RET # return value
declare -i ENT=2 # keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT # a store for unused entropy - start with 1 bit
declare -i BYTES=4 # size of unsigned random bytes returned by od
declare -i BITS=8*BYTES # size of random data returned by od in bits
declare -i CACHE=16 # number of random numbers to cache
declare -i MAX=2**BITS # quantum of entropy per cached random number
declare -i c
function rand(){ # pick a random number from 0 to 2^BITS-1
[[ ${#RCACHE[*]} -eq 0 ]] && { RCACHE=( $(od -An -tu$BYTES -N$CACHE /dev/urandom) ); } # refill cache - could use /dev/random if CACHE is small
RET=${RCACHE[-1]} # pull last random number and scale
unset RCACHE[${#RCACHE[*]}-1] # pop read random number
};
function randBetween(){
local -i N=$1
[[ ENT -lt N ]] && { # not enough entropy to supply ln(N)/ln(2) bits
rand; RND=RET # get more random bits
ENT=MAX # reset entropy
}
RET=RND%N # random number to return
RND=RND/N # remaining randomness
ENT=ENT/N # remaining entropy
};
declare -ia BIN
for (( c=0; c<100000; c++ )); do
randBetween 10
BIN[RET]+=1
done
for c in ${BIN[*]}; do
echo $c
done
推荐文章
- 安装tzdata非交互式
- 在Bash中检查变量是否存在于列表中
- 如何在Ruby中生成a和b之间的随机数?
- 查看PS命令的全部输出
- 确保一次只运行一个shell脚本实例的快速方法
- 如何在Windows命令提示符下运行.sh ?
- 如何从命令行将每两行合并为一行?
- 如何复制在bash所有目录和文件递归?
- java.util.Random真的那么随机吗?我怎么能生成52!(阶乘)可能的序列?
- 从数组中随机选择一个元素
- 在Bash命令提示符上添加git分支
- 匹配前后的Grep字符?
- 如何在Makefile中设置子进程的环境变量
- 带有多个条件的Bash if语句将抛出错误
- 如何让“wc -l”打印没有文件名的行数?