Respuestas:
Uso $RANDOM
. A menudo es útil en combinación con aritmética de shell simple. Por ejemplo, para generar un número aleatorio entre 1 y 10 (inclusive):
$ echo $((1 + RANDOM % 10))
3
El generador real está en variables.c
, la función brand()
. Las versiones anteriores eran un generador lineal simple. La versión 4.0 de bash
utiliza un generador con una cita de un artículo de 1985, lo que presumiblemente significa que es una fuente decente de números pseudoaleatorios. No lo usaría para una simulación (y ciertamente no para criptografía), pero probablemente sea adecuado para tareas básicas de secuencias de comandos.
Si está haciendo algo que requiere números aleatorios serios que puede usar /dev/random
o /dev/urandom
si están disponibles:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
8 y 9 son mensurables (aunque marginalmente) menos probables que 0-7, incluso si $RANDOM
es una fuente sólida de datos aleatorios.
$RANDOM
el rango son 0-32767
los números 0
, se 7
asignan a 3277
diferentes entradas posibles, pero 8
y 9
solo se pueden producir de 3276
diferentes maneras (porque 32768
y 32769
no son posibles). Este es un problema menor para los hacks rápidos, pero significa que el resultado no es uniforme al azar. Las bibliotecas aleatorias, como las de Java Random
, ofrecen funciones para devolver adecuadamente un número aleatorio uniforme en el rango dado, en lugar de simplemente modificar un número no divisible.
Por favor vea $RANDOM
:
$RANDOM
es una función Bash interna (no una constante) que devuelve un entero pseudoaleatorio en el rango de 0 a 32767. No debe usarse para generar una clave de cifrado.
32767
Tiene algún significado especial?
32767
es 2^16 / 2 - 1
cuál es el límite superior para un entero de 16 bits con signo.
2^15 - 1
? Es equivalente, así que tengo curiosidad si hay algún contexto que me falta.
También puede usar shuf (disponible en 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
lugar del final del rango, como este:var=100 && shuf -i 1-${var} -n 1
-n
. Por ejemplo, generar 5 números aleatorios entre 1 y 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
, obtendrá todos los números del 1 al 10 exactamente uno. Si especificas -n 15
, obtendrás solo esos 10 números exactamente una vez. Eso es realmente solo barajar, no generar números aleatorios.
Prueba esto desde tu shell:
$ od -A n -t d -N 1 /dev/urandom
Aquí, -t d
especifica que el formato de salida debe ser con signo decimal; -N 1
dice que lea un byte de /dev/urandom
.
od -A n -t d -N 1 /dev/urandom |tr -d ' '
también puedes obtener un número aleatorio de awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
la semilla es el tiempo de CPU actual. Si necesita especificar una semilla específica, para que RNG pueda duplicarse, use srand(x)
where x
is the seed. Además, citado del manual de funciones numéricas de GNU awk, "diferentes implementaciones de awk usan diferentes generadores de números aleatorios internamente". El resultado es que si está interesado en generar una distribución estadística, debe esperar ligeras variaciones de un tiempo de ejecución a otro en una plataforma diferente (todas en ejecución awk
o gawk
).
Hay $ RANDOM. No sé exactamente cómo funciona. Pero funciona. Para las pruebas, puede hacer:
echo $RANDOM
Me gusta este truco:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
tiene una probabilidad del 67.8% de darle un 1 o un 2, ${RANDOM:0:2}
solo tiene una probabilidad del 0.03% de darle un número de un solo dígito (debe ser 1%), y ambos tienen una probabilidad del 0.003% de darle un 0 Todavía hay casos de uso en los que esto está bien (por ejemplo, entrada no coherente).
Número aleatorio entre 0 y 9 inclusive.
echo $((RANDOM%10))
$RANDOM
solo va de 0 a 32767. Debería haber dicho "Número aleatorio principalmente entre 1 y 3, con algunos extremos";)
Si está utilizando un sistema Linux, puede obtener un número aleatorio de / dev / random o / dev / urandom. Tenga cuidado con / dev / random se bloqueará si no hay suficientes números aleatorios disponibles. Si necesita velocidad sobre aleatoriedad, use / dev / urandom.
Estos "archivos" se llenarán con números aleatorios generados por el sistema operativo. Depende de la implementación de / dev / random en su sistema si obtiene números verdaderos o pseudoaleatorios. Se generan números aleatorios verdaderos con la ayuda del ruido acumulado de los controladores de dispositivos como el mouse, el disco duro y la red.
Puede obtener números aleatorios del archivo con dd
Tomé algunas de estas ideas e hice una función que debería funcionar rápidamente si se requieren muchos números aleatorios.
llamar od
es costoso si necesita muchos números aleatorios. En cambio, lo llamo una vez y almaceno 1024 números aleatorios de / dev / urandom. Cuando rand
se llama, se devuelve el último número aleatorio y se escala. Luego se elimina del caché. Cuando el caché está vacío, se leen otros 1024 números aleatorios.
Ejemplo:
rand 10; echo $RET
Devuelve un número aleatorio en RET entre 0 y 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
ACTUALIZACIÓN: Eso no funciona tan bien para todos los N. También desperdicia bits aleatorios si se usa con pequeños N. Observando que (en este caso) un número aleatorio de 32 bits tiene suficiente entropía para 9 números aleatorios entre 0 y 9 (10 * 9 = 1,000,000,000 <= 2 * 32) podemos extraer múltiples números aleatorios de cada 32 valor fuente aleatorio.
#!/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
generará 10 enteros aleatorios de 32 bits sin signo separados con espacios en blanco. puede almacenarlo en una matriz y usarlo después. Su código parece ser una exageración.
Lectura de archivos especiales de caracteres / dev / random o / dev / urandom es el camino a seguir.
Estos dispositivos devuelven números verdaderamente aleatorios cuando se leen y están diseñados para ayudar al software de aplicación a elegir claves seguras para el cifrado. Tales números aleatorios se extraen de un grupo de entropía que es contribuido por varios eventos aleatorios. {LDD3, Jonathan Corbet, Alessandro Rubini y Greg Kroah-Hartman]
Estos dos archivos son interfaz para aleatorización del núcleo, en particular
void get_random_bytes_arch(void* buf, int nbytes)
que extrae bytes realmente aleatorios del hardware si dicha función es implementada por hardware (por lo general, es), o extrae del grupo de entropía (compuesto de temporizaciones entre eventos como interrupciones del mouse y del teclado y otras interrupciones que están registradas con SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
Esto funciona, pero escribe salidas innecesarias desde dd
stdout. El siguiente comando da solo el número entero que necesito. Incluso puedo obtener el número especificado de bits aleatorios que necesito mediante el ajuste de la máscara de bits dada a la expansión aritmética:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
Tal vez llego un poco tarde, pero ¿qué pasa con el uso jot
para generar un número aleatorio dentro de un rango en Bash?
jot -r -p 3 1 0 1
Esto genera un número aleatorio ( -r
) con 3 decimales de precisión ( -p
). En este caso particular, obtendrá un número entre 0 y 1 ( 1 0 1
). También puede imprimir datos secuenciales. La fuente del número aleatorio, según el manual, es:
Los números aleatorios se obtienen a través de arc4random (3) cuando no se especifica ninguna semilla, y a través de random (3) cuando se da una semilla.
Basado en las excelentes respuestas de @Nelson, @Barun y @Robert, aquí hay un script Bash que genera números aleatorios.
/dev/urandom
cual es mucho mejor que el incorporado de 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
Genere un número aleatorio en el rango de 0 a n (entero de 16 bits con signo). Conjunto de resultados en $ RAND variable. Por ejemplo:
#!/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
Ramificación aleatoria de un programa o sí / no; 1/0; salida verdadero / falso:
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 si eres perezoso para recordar 16383:
if (( RANDOM % 2 )); then
echo "yes"
else
echo "no"
fi