Para ampliar el tema del sesgo de módulo, su fórmula es:
max=$((6*3600))
$(($RANDOM%max/3600))
Y en esta fórmula, $RANDOM
es un valor aleatorio en el rango 0-32767.
RANDOM Each time this parameter is referenced, a random integer between
0 and 32767 is generated.
Ayuda a visualizar cómo esto se asigna a los posibles valores:
0 = 0-3599
1 = 3600-7199
2 = 7200-10799
3 = 10800-14399
4 = 14400-17999
5 = 18000-21599
0 = 21600-25199
1 = 25200-28799
2 = 28800-32399
3 = 32400-32767
Entonces, en su fórmula, la probabilidad de 0, 1, 2 es dos veces mayor que 4, 5. Y la probabilidad de 3 también es ligeramente mayor que 4, 5. De ahí su resultado con 0, 1, 2 como ganadores y 4, 5 como perdedores.
Al cambiar a 9*3600
, resulta que:
0 = 0-3599
1 = 3600-7199
2 = 7200-10799
3 = 10800-14399
4 = 14400-17999
5 = 18000-21599
6 = 21600-25199
7 = 25200-28799
8 = 28800-32399
0 = 32400-32767
1-8 tienen la misma probabilidad, pero todavía hay un ligero sesgo para 0 y, por lo tanto, 0 seguía siendo el ganador en su prueba con 100'000 iteraciones.
Para corregir el sesgo del módulo, primero debe simplificar la fórmula (si solo desea 0-5, entonces el módulo es 6, no 3600 o incluso un número más loco, no tiene sentido). Esta simplificación por sí sola reducirá su sesgo en gran medida (32766 se asigna a 0, 32767 a 1 dando un pequeño sesgo a esos dos números).
Para deshacerse del sesgo por completo, debe volver a tirar, (por ejemplo) cuando $RANDOM
es inferior a 32768 % 6
(eliminar los estados que no se asignan perfectamente al rango aleatorio disponible).
max=6
for f in {1..100000}
do
r=$RANDOM
while [ $r -lt $((32768 % $max)) ]; do r=$RANDOM; done
echo $(($r%max))
done | sort | uniq -c | sort -n
Resultado de la prueba:
16425 5
16515 1
16720 0
16769 2
16776 4
16795 3
La alternativa sería usar una fuente aleatoria diferente que no tenga un sesgo notable (órdenes de magnitud mayores que solo 32768 valores posibles). Pero implementar una lógica de repetición de todos modos no hace daño (incluso si es probable que nunca se cumpla).