Para expandir o tópico de desvio de módulo, sua fórmula é:
max=$((6*3600))
$(($RANDOM%max/3600))
E nesta fórmula, $RANDOM
é um valor aleatório no intervalo de 0 a 32767.
RANDOM Each time this parameter is referenced, a random integer between
0 and 32767 is generated.
Ajuda a visualizar como isso é mapeado para possíveis 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
Portanto, em sua fórmula, a probabilidade de 0, 1, 2 é duas vezes a de 4, 5. E a probabilidade de 3 também é um pouco maior que 4, 5. Daí o seu resultado com 0, 1, 2 como vencedores e 4, 5 como perdedores.
Ao mudar para 9*3600
, acontece como:
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 a 8 têm a mesma probabilidade, mas ainda há um leve viés para 0 e, portanto, 0 ainda foi o vencedor em seu teste com 100'000 iterações.
Para corrigir o viés do módulo, você deve primeiro simplificar a fórmula (se você quiser apenas 0-5, o módulo é 6, não 3600 ou número ainda mais louco, não faz sentido). Somente essa simplificação reduzirá muito seu viés (32766 mapeia para 0, 32767 para 1, dando um pequeno viés para esses dois números).
Para se livrar completamente da polarização, é necessário relançar (por exemplo) quando $RANDOM
for menor que 32768 % 6
(eliminar os estados que não são mapeados perfeitamente para o intervalo aleatório disponível).
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 do teste:
16425 5
16515 1
16720 0
16769 2
16776 4
16795 3
A alternativa seria usar uma fonte aleatória diferente que não tenha um viés perceptível (ordens de magnitude maiores que apenas 32768 valores possíveis). Mas implementar uma lógica de relançamento de qualquer maneira não é prejudicial (mesmo que provavelmente nunca aconteça).