Pour développer le sujet du biais modulo, votre formule est la suivante:
max=$((6*3600))
$(($RANDOM%max/3600))
Et dans cette formule, $RANDOM
est une valeur aléatoire dans la plage 0-32767.
RANDOM Each time this parameter is referenced, a random integer between
0 and 32767 is generated.
Il aide à visualiser comment cela correspond aux valeurs possibles:
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
Donc, dans votre formule, la probabilité de 0, 1, 2 est le double de 4, 5. Et la probabilité de 3 est légèrement supérieure à 4, 5 également. D'où votre résultat avec 0, 1, 2 comme gagnants et 4, 5 comme perdants.
Lors du passage à 9*3600
, il s'avère 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 ont la même probabilité, mais il y a toujours un léger biais pour 0, et donc 0 était toujours le vainqueur de votre test avec 100'000 itérations.
Pour corriger le biais du modulo, vous devez d'abord simplifier la formule (si vous ne voulez que 0-5, alors le modulo est 6, pas 3600 ou un nombre encore plus fou, cela n'a aucun sens). À elle seule, cette simplification réduira considérablement votre biais (32766 correspond à 0, 32767 à 1, ce qui donne un tout petit biais à ces deux nombres).
Pour éliminer complètement le biais, vous devez relancer (par exemple) quand $RANDOM
est inférieur à 32768 % 6
(éliminer les états qui ne correspondent pas parfaitement à la plage aléatoire 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
Résultat du test:
16425 5
16515 1
16720 0
16769 2
16776 4
16795 3
L'alternative serait d'utiliser une source aléatoire différente qui n'a pas de biais notable (ordres de grandeur supérieurs à seulement 32 768 valeurs possibles). Mais l'implémentation d'une logique de relance de toute façon ne fait pas de mal (même si cela n'arrive probablement jamais).