Modulo önyargı konusunu genişletmek için formülünüz:
max=$((6*3600))
$(($RANDOM%max/3600))
Ve bu formülde, $RANDOM
0-32767 aralığında rastgele bir değerdir.
RANDOM Each time this parameter is referenced, a random integer between
0 and 32767 is generated.
Bunun olası değerlerle nasıl eşleştiğini görselleştirmeye yardımcı olur:
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
Formülünüzde, 0, 1, 2 olasılığı 4, 5'in iki katıdır. 3 olasılığı da 4, 5'ten biraz daha yüksektir. Sonuç olarak kazananlar olarak 0, 1, 2 ve kaybedenler olarak 4, 5 elde edersiniz.
Olarak değiştirirken 9*3600
, şu şekilde ortaya çıkar:
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 aynı olasılığa sahiptir, ancak 0 için hala hafif bir önyargı vardır ve bu nedenle 0, 100.000 yineleme ile testinizde hala kazanan oldu.
Modulo yanlılığını düzeltmek için, önce formülü basitleştirmelisiniz (sadece 0-5 istiyorsanız, modulo 3600, hatta daha çılgın bir sayıdır, bunun anlamı yok). Bu sadeleştirme tek başına önyargınızı çok azaltacaktır (32766, 0, 32767 ila 1 arasındadır) bu iki sayıya küçük bir önyargı verir).
Önyargıdan tamamen kurtulmak için, (örneğin) $RANDOM
, daha düşük olduğunda yeniden döndürmeniz gerekir ( 32768 % 6
mükemmel rasgele aralığa mükemmel şekilde eşlenmeyen durumları ortadan kaldırın).
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
Test sonucu:
16425 5
16515 1
16720 0
16769 2
16776 4
16795 3
Alternatif, fark edilebilir önyargıya sahip olmayan farklı bir rastgele kaynak kullanmak olabilir (sadece 32768 olası değerlerden daha büyük büyüklük sıraları). Ancak yine de bir roll-roll mantığı uygulamak acıtmaz (muhtemelen hiç geçmeyecek olsa bile).