Generar números aleatoriamente con shuf

12 Septiembre 2018 by 0 Comment Programación 6618 Views
Valora este artículo
(0 votos)

Ya hemos visto que, dado que %$valor lo que hace es calcular el resto de la división entre la cifra que precede a % (dividendo) y la cifra que sucede a % (divisor), $RANDOM%limitesuperior no vale para generar números aleatorios de forma fideligna (a no ser que seamos trileros, pero en este caso no buscamos una verdadera aleatoriedad).

También hemos visto que shuf sí que sirve para crear órdenes aleatorios. Y ahora vamos a ver cómo usar shuf para generar números aleatorios.

Lanzamiento a cara o cruz de una moneda (aleatoriedad entre dos valores)

Veamos cómo usar shuf en el primer ejemplo que usé en contra de $RANDOM: una aleatoriedad dos valores. Pero antes de ello, vuelvo a remarcar que shuf no genera nada, sino que hace un orden aleatorio de una lista. Así que primero hay que generar una lista y luego ordenar aleatoriamente con shuf.

¿Qué formas podemos generar una lista?

Veamos varias formas de hacerlo:

En un fichero auxiliar:

#/bin/bash

let comienzo=0
let final=1

for i in $(seq $comienzo $final)
do
    echo $i >> numeros.txt
done

Y ahora podemos ejecutarlo y luego ordenar con shuf. Veamos a ver si la aleatoriedad es tal:

 

En este pantallazo vemos que de 12 tiradas, han salido siete veces 0 y cinco veces 1. Está dentro de la normalidad. Pero vamos a ver qué ocurre si tiramos mil veces la moneda:

#/bin/bash

let ceros=0
let unos=0

for i in $(seq 1 1000)
do
    let moneda=$(shuf -n1 numeros.txt)
    if [ $moneda -eq 0 ]
    then
        let ceros++
    else
        let unos++
    fi
done

echo "El número de ceros que ha salido es: "$ceros
echo "El número de unos que ha salido es: "$unos

Y lo comprobamos (vuelvo a poner pantallazo para que se vea que no hay trampa ni cartón):

comprobacionconfichero.png

 

¡Incluso me ha llegado a dar un empate de 500 a 500!

Visto que shuf es más válido en este caso, vamos a ver cómo generar una lista aleatoria con shuf. Compruebo en el mismo script para evitar hacer un artículo excesivamente largo:

#/bin/bash

let ceros=0
let unos=0

for i in $(seq 1 1000)
do
    numeros=$(shuf -i 0-1)    
    if [[ ${numeros:0:1} == "0" ]]
    then
        let ceros++
    else
        let unos++
    fi
done

echo "El número de ceros que ha salido es: "$ceros
echo "El número de unos que ha salido es: "$unos

listaconshuf.png

 

Funciona... y de nuevo hemos tenido un empate a 500 en una tirada.

Pero ahora te puedes preguntar, por qué si existe el parámetro -i en shuf para generar una lista con orden aleatorio y el parámetro -n para extraer un número determinado de elementos, ¿por qué no lo usas en la misma línea?

No te falta razón para pensarlo, pero quería mostrar distintas formas de lanzar la moneda. Y hacer un artículo evolutivo que acabase con la mejor opción:

#/bin/bash

let ceros=0
let unos=0

for i in $(seq 1 1000)
do
    numeros=$(shuf -i 0-1 -n 1)    
    if [[ $numeros == "0" ]]
    then
        let ceros++
    else
        let unos++
    fi
done

echo "El número de ceros que ha salido es: "$ceros
echo "El número de unos que ha salido es: "$unos

listaconshufin.png

Y vuelve a funcionar... incluso me ha dado otro empate a 500.

¿Y si en lugar de tirar a cara o cruz hacemos un rango mayor, por ejemplo de 0 a 1000?

Simplemente le cambiamos el rango en -i. Y si además, para comprobar si funciona, vamos a aumentar el número de tiradas.

#/bin/bash

let ceros=0
let quinientos=0
let miles=0

for i in $(seq 1 10000)
do
    numeros=$(shuf -i 0-1000 -n 1)    
    if [[ $numeros == "0" ]]
    then
        let ceros++
    elif [[ $numeros == "500" ]]
    then
        let quinientos++
    elif [[ $numeros == "1000" ]]
    then
        let miles++
    fi
done

echo "El número de ceros que ha salido es: "$ceros
echo "El número de quinientos que ha salido es: "$quinientos
echo "El número de miles que ha salido es: "$miles

Y al probarlo, da unos resultados tales como:

 

 

delunoalmil.png

 

Que son unos resultados que son totalmente coherentes dentro de lo que es la aleatoriedad por lo que podemos decir que la mejor forma para generar un número aleatorio en Bash es

shuf -i $limiteinferior-$limitesuperior -n 1

Información adicional

  • Nivel de dificultad: Medio
  • ¿Tutorial sacado de otra web/foro?: No

¡Atención! Este sitio usa cookies y tecnologías similares.

Si no cambia la configuración de su navegador, usted acepta su uso. Saber más

Acepto

Vea nuestra política de cookies y enlaces de interés aquí