Eu li sobre RNGs na Wikipedia e $RANDOM
função no TLDP, mas isso realmente não explica esse resultado:
$ max=$((6*3600))
$ for f in {1..100000}; do echo $(($RANDOM%max/3600)); done | sort | uniq -c
21787 0
22114 1
21933 2
12157 3
10938 4
11071 5
Por que os valores acima são cerca de 2x mais inclinados a serem 0, 1, 2 do que 3, 4, 5, mas quando altero o módulo máximo, eles estão quase igualmente distribuídos pelos 10 valores?
$ max=$((9*3600))
$ for f in {1..100000}; do echo $(($RANDOM%max/3600)); done | sort | uniq -c
11940 0
11199 1
10898 2
10945 3
11239 4
10928 5
10875 6
10759 7
11217 8
$RANDOM
variável não usa um bom PRNG internamente.Respostas:
Para expandir o tópico de desvio de módulo, sua fórmula é:
E nesta fórmula,
$RANDOM
é um valor aleatório no intervalo de 0 a 32767.Ajuda a visualizar como isso é mapeado para possíveis valores:
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: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 que32768 % 6
(eliminar os estados que não são mapeados perfeitamente para o intervalo aleatório disponível).Resultado do teste:
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).
fonte
Isso é parcialidade do módulo. Se
RANDOM
for bem construído, cada valor entre 0 e 32767 é produzido com igual probabilidade. Ao usar o módulo, você altera as probabilidades: as probabilidades de todos os valores acima do módulo são adicionadas aos valores para os quais são mapeados.No seu exemplo, 6 × 3600 é aproximadamente dois terços do intervalo de valores. As probabilidades do terço superior são, portanto, adicionadas às do terço inferior, o que significa que valores de 0 a 2 (aproximadamente) são duas vezes mais prováveis de serem produzidos do que valores de 3 a 5. 9 × 3600 é quase 32767, portanto, o o viés do módulo é muito menor e afeta apenas valores de 32400 a 32767.
Para responder à sua pergunta principal, pelo menos no Bash, a sequência aleatória é totalmente previsível se você conhece a semente. Veja
intrand32
emvariables.c
.fonte