$RANDOM est une fonction interne Bash (pas une constante) renvoyant un entier pseudo aléatoire dans l'intervalle 0 - 32767. $RANDOM ne devrait pas être utilisé pour générer une clé de cryptage.
Exemple 9-23. Générer des nombres aléatoires
#!/bin/bash
# $RANDOM renvoie un entier différent à chaque invocation.
# Echelle: 0 - 32767 (entier signé sur 16 bits).
NBMAX=10
index=1
echo
echo "$NBMAX nombres aléatoires:"
echo "-----------------"
while [ "$index" -le $NBMAX ] # Génère 10 ($NBMAX) entiers aléatoires.
do
nombre=$RANDOM
echo $nombre
let "index += 1" # Increment index.
done
echo "-----------------"
# Si vous avez besoin d'un entier aléatoire dans une certaine échelle, utilisez
#+ l'opérateur 'modulo'.
# Il renvoie le reste d'une division.
ECHELLE=500
echo
nombre=$RANDOM
let "nombre %= $ECHELLE"
echo "Nombre aléatoire inférieur à $ECHELLE --- $nombre"
echo
# Si vous avez besoin d'un entier aléatoire supérieur à une borne, alors
# faites un test pour annuler tous les nombres en dessous de cette borne.
PLANCHER=200
nombre=0 #initialise
while [ "$nombre" -le $PLANCHER ]
do
nombre=$RANDOM
done
echo "Nombre aléatoire supérieur à $PLANCHER --- $nombre"
echo
# Vous pouvez combiner les deux techniques pour récupérer un nombre aléatoire
# compris entre deux limites.
nombre=0 #initialise
while [ "$nombre" -le $PLANCHER ]
do
nombre=$RANDOM
let "nombre %= $ECHELLE" # Met $nombre sous $ECHELLE.
done
echo "Nombre aléatoire compris entre $PLANCHER et $ECHELLE --- $nombre"
echo
# Génère un choix binaire, c'est-à-dire "vrai" ou "faux".
BINAIRE=2
nombre=$RANDOM
T=1
let "nombre %= $BINAIRE"
# let "nombre >>= 14" donne une meilleure distribution aléatoire
# (les décalages droits enlèvent tout sauf le dernier nombre binaire).
if [ "$nombre" -eq $T ]
then
echo "VRAI"
else
echo "FAUX"
fi
echo
# Peut générer des matrices (??).
SPOTS=7 # Modulo 7 donne une échelle de 0 à 6.
DICE=2
ZERO=0
die1=0
die2=0
# Jette chaque dé séparément, et donne ainsi une chance correcte.
while [ "$die1" -eq $ZERO ] # Un zéro ne peut pas arriver.
do
let "die1 = $RANDOM % $SPOTS" # Le premier.
done
while [ "$die2" -eq $ZERO ]
do
let "die2 = $RANDOM % $SPOTS" # Le deuxième.
done
let "throw = $die1 + $die2"
echo "Throw of the dice = $throw"
echo
exit 0 |
Exemple 9-24. Piocher une carte au hasard dans un tas
#!/bin/bash
# pick-card.sh
# Ceci est un exemple pour choisir au hasard un élément d'un tableau.
# Prenez une carte, n'importe quelle carte.
Suites="Carre
Pique
Coeur
Trefle"
Denominations="2
3
4
5
6
7
8
9
10
Jack
Queen
King
Ace"
suite=($Suites) # Mettre dans une variable de type tableau.
denomination=($Denominations)
num_suites=${#suite[*]} # Compter le nombre d'éléments.
num_denominations=${#denomination[*]}
echo -n "${denomination[$((RANDOM%num_denominations))]} of "
echo ${suite[$((RANDOM%num_suites))]}
# $bozo sh pick-cards.sh
# Jack of Clubs
# Merci, "jipe", pour m'avoir indiqué cette utilisation de $RANDOM.
exit 0 |
![]() | Jipe nous a indiqué un autre ensemble de techniques pour générer des nombres aléatoires à l'intérieur d'un intervalle donné.
|
A quel point $RANDOM est-il aléatoire? la meilleur façon de le tester est d'écrire un script qui enregistre la suite des nombres << aléatoires >> générés par $RANDOM. Faisons tourner $RANDOM plusieurs fois...
Exemple 9-25. Laisser tourner RANDOM plusieurs fois
#!/bin/bash
# A quel point RANDOM est aléatoire?
RANDOM=$$ # Réinitialise le générateur de nombres aléatoires en utilisant
#+ le PID du script.
PIPS=6 # A die has 6 pips.
COMPTEURMAX=600# Augmentez ceci, si vous n'avez rien de mieux à faire.
compteur=0 # Compteur.
zeros=0 # Doit initialiser les comptes à zéro.
uns=0 # car une variable non initialisée est null, et ne vaut pas zéro.
deux=0
trois=0
quatre=0
cinq=0
six=0
Affiche_resultat ()
{
echo
echo "uns = $uns"
echo "deux = $deux"
echo "trois = $trois"
echo "quatre = $quatre"
echo "cinq = $cinq"
echo "six = $six"
echo
}
mise_a_jour_compteur()
{
case "$1" in
0) let "uns += 1";; # Comme die n'a pas de "zéro", ceci correspond à 1.
1) let "deux += 1";; # Et ceci à 2, etc.
2) let "trois += 1";;
3) let "quatre += 1";;
4) let "cinq += 1";;
5) let "six += 1";;
esac
}
echo
while [ "$compteur" -lt "$COMPTEURMAX" ]
do
let "die1 = RANDOM % $PIPS"
mise_a_jour_compteur $die1
let "compteur += 1"
done
Affiche_resultat
# Les scores devraient être distribués de façon égale, en supposant que RANDOM
#+ soit correctement aléatoire.
# Avec $COMPTEURMAX à 600, tout devrait tourner autour de 100, plus ou moins
#+ 20.
#
# Gardez en tête que RANDOM est un générateur pseudo-aléatoire,
# et pas un particulièrement bon.
# Exercice (facile):
# ---------------
# Réécrire ce script pour lancer une pièce 1000 fois.
# Les choix sont "PILE" ou "FACE".
exit 0 |
Comme nous avons vu sur le dernier exemple, il est préférable de << réinitialiser >> le générateur RANDOM à chaque fois qu'il est invoqué. Utiliser le même germe pour RANDOM ne fera que répéter la même série de nombres. (Ceci reflète le comportement de la fonction C random().)
Exemple 9-26. Réinitialiser RANDOM
#!/bin/bash
# seeding-random.sh: Utiliser la variable RANDOM.
NBMAX=25 # How many numbers to generate.
nombres_aleatoires ()
{
compteur=0
while [ "$compteur" -lt "$NBMAX" ]
do
nombre=$RANDOM
echo -n "$nombre "
let "compteur += 1"
done
}
echo; echo
RANDOM=1 # Initialiser RANDOM met en place le générateur de nombres
#+ aléatoires.
nombres_aleatoires
echo; echo
RANDOM=1 # Même élément pour RANDOM...
nombres_aleatoires # ...reproduit la même série de nombres.
#
# Quand est-il utile de dupliquer une série de nombres
#+ "aléatoires"?
echo; echo
RANDOM=2 # Nouvel essai, mais avec un 'seed' différent...
nombres_aleatoires # donne une autre série...
echo; echo
# RANDOM=$$ initialise RANDOM à partir du PID du script.
# Il est aussi possible d'initialiser RANDOM à partir des commandes 'time' et
#+ 'date'.
# Un peu plus d'amusement...
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }')
# Sortie pseudo-aléatoire récupéré de /dev/urandom (fichier périphérique
#+ pseudo-aléatoire),
#+ puis convertit la ligne en nombres (octal) affichables avec "od".
#+ Finalement "awk" récupère un seul nombre pour SEED.
RANDOM=$SEED
nombres_aleatoires
echo; echo
exit 0 |
![]() | Le fichier périphérique /dev/urandom apporte un moyen de générer des nombres pseudo aléatoires bien plus << aléatoires >> que la variable $RANDOM. dd if=/dev/urandom of=fichier_cible bs=1 count=XX crée un fichier de nombres pseudo aléatoires bien distribués. Néanmoins, assigner ces nombres à une variable dans un script nécessite un petit travail supplémentaire, tel qu'un filtrage par l'intermédiaire de od (comme dans l'exemple ci-dessus) ou tel que l'utilisation de dd (voir Exemple 12-42). Il existe aussi d'autres moyens de générer des nombres pseudo aléatoires dans un script. Awk propose une façon agréable de le faire. Exemple 9-27. Nombres pseudo aléatoires, en utilisant awk
|
| Précédent | Sommaire | Suivant |
| Références indirectes aux variables | Niveau supérieur | La construction en double parenthèse |