Respostas:
Use $RANDOM
. Geralmente é útil em combinação com a aritmética simples do shell. Por exemplo, para gerar um número aleatório entre 1 e 10 (inclusive):
$ echo $((1 + RANDOM % 10))
3
O gerador atual está dentro variables.c
, a função brand()
. As versões mais antigas eram um gerador linear simples. A versão 4.0 de bash
usa um gerador com uma citação de um artigo de 1985, o que presumivelmente significa que é uma fonte decente de números pseudo-aleatórios. Eu não o usaria para uma simulação (e certamente não para criptografia), mas provavelmente é adequado para tarefas básicas de script.
Se você estiver fazendo algo que exija números aleatórios sérios, poderá usar /dev/random
ou /dev/urandom
se estiverem disponíveis:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
, 8 e 9 são mensuráveis (embora marginalmente) menos prováveis que 0-7, mesmo que $RANDOM
seja uma fonte robusta de dados aleatórios.
$RANDOM
o intervalo é 0-32767
o número 0
- 7
mapeie para 3277
diferentes entradas possíveis, mas 8
e 9
só pode ser produzido de 3276
maneiras diferentes (porque 32768
e 32769
não são possíveis). Esse é um problema menor para hacks rápidos, mas significa que o resultado não é uniformemente aleatório. Bibliotecas aleatórias, como as de Java Random
, oferecem funções para retornar adequadamente um número aleatório uniforme no intervalo especificado, em vez de simplesmente modificar um número não divisível.
Por favor veja $RANDOM
:
$RANDOM
é uma função Bash interna (não uma constante) que retorna um número inteiro pseudoaleatório no intervalo de 0 a 32767. Não deve ser usada para gerar uma chave de criptografia.
32767
tem algum significado especial?
32767
é 2^16 / 2 - 1
o limite superior para um número inteiro assinado de 16 bits.
2^15 - 1
? É equivalente, então estou curioso para saber se há algum contexto em falta?
Você também pode usar shuf (disponível em coreutils).
shuf -i 1-100000 -n 1
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
ao invés do fim gama, como este:var=100 && shuf -i 1-${var} -n 1
-n
. Por exemplo, gere 5 números aleatórios entre 1 e 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
, obterá todos os números de 1 a 10, exatamente um. Se você especificar -n 15
, ainda receberá apenas esses 10 números exatamente uma vez. Isso é realmente apenas baralhar, não gerar números aleatórios.
Tente isso no seu shell:
$ od -A n -t d -N 1 /dev/urandom
Aqui, -t d
especifica que o formato de saída deve ser assinado como decimal; -N 1
diz para ler um byte de /dev/urandom
.
od -A n -t d -N 1 /dev/urandom |tr -d ' '
você também pode obter um número aleatório do awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
a semente é o tempo atual da CPU. Se você precisar especificar uma semente específica, para que o RNG possa ser duplicado, use srand(x)
onde x
está a semente. Além disso, citado no manual de funções numéricas do GNU awk, "diferentes implementações do awk usam diferentes geradores de números aleatórios internamente". O resultado é que, se você estiver interessado em gerar distribuição estatística, espere pequenas variações passando de um tempo de execução para outro em uma plataforma diferente (todas em execução awk
ou gawk
).
Há $ ALEATÓRIO. Não sei exatamente como isso funciona. Mas funciona. Para testar, você pode fazer:
echo $RANDOM
Eu gosto deste truque:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
tem 67,8% de chance de fornecer 1 ou 2, ${RANDOM:0:2}
apenas 0,03% de chance de fornecer um número de dígito único (deve ser 1%) e ambos têm 0,003% de chance de fornecer 0 Ainda existem casos de uso em que isso é bom (por exemplo, entrada não consistente).
Número aleatório entre 0 e 9, inclusive.
echo $((RANDOM%10))
$RANDOM
só vai de 0 a 32767. Deveria ter dito "Número aleatório principalmente entre 1 e 3, com alguns alas";)
Se você estiver usando um sistema Linux, poderá obter um número aleatório de / dev / random ou / dev / urandom. Tenha cuidado / dev / random irá bloquear se não houver números aleatórios suficientes disponíveis. Se você precisar de velocidade acima da aleatoriedade, use / dev / urandom.
Esses "arquivos" serão preenchidos com números aleatórios gerados pelo sistema operacional. Depende da implementação de / dev / random no seu sistema se você obtiver números verdadeiros ou pseudo-aleatórios. Números aleatórios verdadeiros são gerados com a ajuda do ruído coletado de drivers de dispositivos como mouse, disco rígido e rede.
Você pode obter números aleatórios do arquivo com dd
Eu peguei algumas dessas idéias e criei uma função que deveria ser executada rapidamente se forem necessários muitos números aleatórios.
ligar od
é caro se você precisar de muitos números aleatórios. Em vez disso, chamo uma vez e armazeno 1024 números aleatórios em / dev / urandom. Quandorand
é chamado, o último número aleatório é retornado e redimensionado. É então removido do cache. Quando o cache está vazio, outros 1024 números aleatórios são lidos.
Exemplo:
rand 10; echo $RET
Retorna um número aleatório no RET entre 0 e 9, inclusive.
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
UPDATE: Isso não funciona tão bem para todos os N. Ele também desperdiça bits aleatórios se usado com N. pequeno. Observando que (nesse caso) um número aleatório de 32 bits tem entropia suficiente para 9 números aleatórios entre 0 e 9 (10 * 9 = 1.000.000.000 <= 2 * 32), podemos extrair vários números aleatórios de cada 32 valor fonte aleatório.
#!/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
od -An -tu4 -N40 /dev/urandom
irá gerar 10 números inteiros aleatórios e não assinados, separados por espaços em branco. você pode armazená-lo em uma matriz e usá-lo posteriormente. seu código parece ser um exagero.
Ler arquivos especiais de caracteres / dev / random ou / dev / urandom é o caminho a percorrer.
Esses dispositivos retornam números verdadeiramente aleatórios quando lidos e foram projetados para ajudar o software aplicativo a escolher chaves seguras para criptografia. Esses números aleatórios são extraídos de um pool de entropia que é contribuído por vários eventos aleatórios. {LDD3, Jonathan Corbet, Alessandro Rubini e Greg Kroah-Hartman]
Esses dois arquivos são uma interface para a randomização do kernel, em particular
void get_random_bytes_arch(void* buf, int nbytes)
que extrai bytes verdadeiramente aleatórios do hardware, se essa função é implementada pelo hardware (geralmente é), ou extrai do pool de entropia (composto por tempos entre eventos como interrupções de mouse e teclado e outras interrupções registradas no SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
Isso funciona, mas grava saída desnecessária de dd
para stdout. O comando abaixo fornece apenas o número inteiro que eu preciso. Posso até obter um número especificado de bits aleatórios, conforme necessário, ajustando a máscara de bits dada à expansão aritmética:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
Talvez eu esteja um pouco atrasado, mas e quanto a usar jot
para gerar um número aleatório dentro de um intervalo no Bash?
jot -r -p 3 1 0 1
Isso gera um -r
número aleatório ( ) com precisão de 3 casas decimais ( -p
). Nesse caso específico, você obterá um número entre 0 e 1 ( 1 0 1
). Você também pode imprimir dados seqüenciais. A fonte do número aleatório, de acordo com o manual, é:
Os números aleatórios são obtidos através do arc4random (3) quando nenhuma semente é especificada e através do aleatório (3) quando uma semente é fornecida.
Com base nas ótimas respostas de @Nelson, @Barun e @Robert, aqui está um script Bash que gera números aleatórios.
/dev/urandom
que é muito melhor do que o built-in do Bash$RANDOM
#!/usr/bin/env bash
digits=10
rand=$(od -A n -t d -N 2 /dev/urandom |tr -d ' ')
num=$((rand % 10))
while [ ${#num} -lt $digits ]; do
rand=$(od -A n -t d -N 1 /dev/urandom |tr -d ' ')
num="${num}$((rand % 10))"
done
echo $num
Gere um número aleatório no intervalo de 0 a n (número inteiro assinado de 16 bits). Conjunto de resultados na variável $ RAND. Por exemplo:
#!/bin/bash
random()
{
local range=${1:-1}
RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
let "RAND=$RAND%($range+1)"
}
n=10
while [ $(( n -=1 )) -ge "0" ]; do
random 500
echo "$RAND"
done
Ramificação aleatória de um programa ou sim / não; 1/0; saída verdadeira / falsa:
if [ $RANDOM -gt 16383 ]; then # 16383 = 32767/2
echo var=true/1/yes/go_hither
else
echo var=false/0/no/go_thither
fi
de se você tem preguiça de lembrar 16383:
if (( RANDOM % 2 )); then
echo "yes"
else
echo "no"
fi