Réponses:
Utilisez $RANDOM
. Il est souvent utile en combinaison avec une simple arithmétique de coque. Par exemple, pour générer un nombre aléatoire entre 1 et 10 (inclus):
$ echo $((1 + RANDOM % 10))
3
Le générateur réel est dans variables.c
la fonction brand()
. Les anciennes versions étaient un simple générateur linéaire. La version 4.0 bash
utilise un générateur avec une citation d'un article de 1985, ce qui signifie probablement que c'est une source décente de nombres pseudo-aléatoires. Je ne l'utiliserais pas pour une simulation (et certainement pas pour la cryptographie), mais c'est probablement suffisant pour les tâches de script de base.
Si vous faites quelque chose qui nécessite des nombres aléatoires sérieux, vous pouvez les utiliser /dev/random
ou /dev/urandom
s'ils sont disponibles:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
, 8 et 9 sont mesurables (bien que marginalement) moins probables que 0-7, même s'il $RANDOM
s'agit d'une source robuste de données aléatoires.
$RANDOM
la plage est constituée de 0-32767
nombres 0
- 7
mappez sur 3277
différentes entrées possibles, mais 8
et 9
ne pouvez être produites que de 3276
différentes manières (car 32768
et 32769
ne sont pas possibles). Il s'agit d'un problème mineur pour les hacks rapides, mais cela signifie que le résultat n'est pas uniformément aléatoire. Les bibliothèques aléatoires, comme Java Random
, offrent des fonctions pour renvoyer correctement un nombre aléatoire uniforme dans la plage donnée, plutôt que de simplement modifier un nombre non divisible.
Veuillez voir $RANDOM
:
$RANDOM
est une fonction Bash interne (pas une constante) qui renvoie un entier pseudo-aléatoire dans la plage 0 - 32767. Elle ne doit pas être utilisée pour générer une clé de chiffrement.
32767
une signification particulière?
32767
est 2^16 / 2 - 1
la limite supérieure d'un entier signé de 16 bits.
2^15 - 1
? C'est équivalent, donc je suis juste curieux de savoir s'il y a un contexte qui me manque?
Vous pouvez également utiliser shuf (disponible dans 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
au lieu de la fin de la plage, comme ceci:var=100 && shuf -i 1-${var} -n 1
-n
. Par exemple, générer 5 nombres aléatoires entre 1 et 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
vous obtiendrez tous les nombres de 1 à 10 exactement. Si vous spécifiez, -n 15
vous n'obtiendrez toujours qu'une seule fois ces 10 numéros. Ce n'est que du brassage, pas de génération de nombres aléatoires.
Essayez ceci depuis votre shell:
$ od -A n -t d -N 1 /dev/urandom
Ici, -t d
spécifie que le format de sortie doit être signé décimal; -N 1
dit de lire un octet de /dev/urandom
.
od -A n -t d -N 1 /dev/urandom |tr -d ' '
vous pouvez également obtenir un nombre aléatoire de awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
le germe est le temps CPU actuel. Si vous devez spécifier une graine spécifique, afin que RNG puisse être dupliqué, utilisez srand(x)
où x
est la graine. Également, cité dans le manuel des fonctions numériques de GNU awk, «différentes implémentations awk utilisent différents générateurs de nombres aléatoires en interne». Le résultat est que si vous souhaitez générer une distribution statistique, vous devez vous attendre à de légères variations allant d'un runtime à l'autre sur une plateforme différente (toutes en cours d'exécution awk
ou gawk
).
Il y a $ RANDOM. Je ne sais pas exactement comment ça marche. Mais ça marche. Pour les tests, vous pouvez faire:
echo $RANDOM
J'aime cette astuce:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
a 67,8% de chances de vous donner un 1 ou un 2, ${RANDOM:0:2}
n'a que 0,03% de chances de vous donner un numéro à un chiffre (devrait être de 1%), et les deux ont 0,003% de chances de vous donner un 0 Il existe encore des cas d'utilisation où cela est correct (par exemple, entrée non cohérente).
Nombre aléatoire entre 0 et 9 inclus.
echo $((RANDOM%10))
$RANDOM
ne va que de 0 à 32767. Il aurait dû dire "Nombre aléatoire principalement entre 1 et 3, avec quelques ailiers";)
Si vous utilisez un système Linux, vous pouvez obtenir un nombre aléatoire dans / dev / random ou / dev / urandom. Attention, dev / random bloquera s'il n'y a pas assez de nombres aléatoires disponibles. Si vous avez besoin de vitesse par rapport à l'aléatoire, utilisez / dev / urandom.
Ces "fichiers" seront remplis de nombres aléatoires générés par le système d'exploitation. Cela dépend de l'implémentation de / dev / random sur votre système si vous obtenez des nombres vrais ou pseudo aléatoires. De vrais nombres aléatoires sont générés avec l'aide du bruit provenant des pilotes de périphériques comme la souris, le disque dur, le réseau.
Vous pouvez obtenir des nombres aléatoires à partir du fichier avec dd
J'ai pris quelques-unes de ces idées et créé une fonction qui devrait fonctionner rapidement si de nombreux nombres aléatoires sont nécessaires.
appeler od
coûte cher si vous avez besoin de beaucoup de numéros aléatoires. Au lieu de cela, je l'appelle une fois et stocke 1024 numéros aléatoires à partir de / dev / urandom. Lorsque rand
est appelé, le dernier nombre aléatoire est renvoyé et mis à l'échelle. Il est ensuite supprimé du cache. Lorsque le cache est vide, 1024 autres nombres aléatoires sont lus.
Exemple:
rand 10; echo $RET
Renvoie un nombre aléatoire dans RET compris entre 0 et 9 inclus.
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
MISE À JOUR: Cela ne fonctionne pas si bien pour tous les N. Il gaspille également des bits aléatoires s'il est utilisé avec de petits N. Notant que (dans ce cas) un nombre aléatoire de 32 bits a suffisamment d'entropie pour 9 nombres aléatoires entre 0 et 9 (10 * 9 = 1 000 000 000 <= 2 * 32), nous pouvons extraire plusieurs nombres aléatoires de chaque 32 valeur source aléatoire.
#!/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
générera 10 entiers aléatoires non signés de 32 bits séparés par des espaces. vous pouvez le stocker dans un tableau et l'utiliser ensuite. votre code semble exagéré.
La lecture à partir de fichiers spéciaux de caractères / dev / random ou / dev / urandom est la voie à suivre.
Ces appareils renvoient des nombres vraiment aléatoires lorsqu'ils sont lus et sont conçus pour aider les logiciels d'application à choisir des clés sécurisées pour le chiffrement. Ces nombres aléatoires sont extraits d'un pool d'entropie alimenté par divers événements aléatoires. {LDD3, Jonathan Corbet, Alessandro Rubini et Greg Kroah-Hartman]
Ces deux fichiers sont une interface pour la randomisation du noyau, en particulier
void get_random_bytes_arch(void* buf, int nbytes)
qui tire des octets vraiment aléatoires du matériel si une telle fonction est implémentée par le matériel (généralement), ou il tire du pool d'entropie (composé de temporisations entre les événements comme les interruptions de souris et de clavier et d'autres interruptions enregistrées avec SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
Cela fonctionne, mais écrit la sortie inutile de dd
à stdout. La commande ci-dessous donne juste l'entier dont j'ai besoin. Je peux même obtenir le nombre spécifié de bits aléatoires dont j'ai besoin en ajustant le masque de bits donné à l'expansion arithmétique:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
Je suis peut-être un peu trop tard, mais qu'en est-il de l'utilisation jot
pour générer un nombre aléatoire dans une plage dans Bash?
jot -r -p 3 1 0 1
Cela génère un nombre aléatoire ( -r
) avec une précision de 3 décimales ( -p
). Dans ce cas particulier, vous obtiendrez un nombre entre 0 et 1 ( 1 0 1
). Vous pouvez également imprimer des données séquentielles. La source du nombre aléatoire, selon le manuel, est:
Les nombres aléatoires sont obtenus via arc4random (3) lorsqu'aucune graine n'est spécifiée, et via random (3) lorsqu'une graine est donnée.
Basé sur les bonnes réponses de @Nelson, @Barun et @Robert, voici un script Bash qui génère des nombres aléatoires.
/dev/urandom
ce qui est bien meilleur que le Bash intégré$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
Générez un nombre aléatoire dans la plage de 0 à n (entier 16 bits signé). Jeu de résultats dans la variable $ RAND. Par exemple:
#!/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
Branchement aléatoire d'un programme ou oui / non; 1/0; sortie vrai / faux:
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 vous paresseux de vous rappeler 16383:
if (( RANDOM % 2 )); then
echo "yes"
else
echo "no"
fi