Щоб розширити тему зміщення модуля, ваша формула:
max=$((6*3600))
$(($RANDOM%max/3600))
І в цій формулі $RANDOM
є випадкове значення в діапазоні 0-32767.
RANDOM Each time this parameter is referenced, a random integer between
0 and 32767 is generated.
Це допомагає візуалізувати, як це відображає можливі значення:
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
Тож у вашій формулі ймовірність для 0, 1, 2 вдвічі більша за 4, 5. І ймовірність 3 трохи більша, ніж 4, 5 теж. Звідси ваш результат із 0, 1, 2 як переможці та 4, 5 як переможені.
При зміні на 9*3600
це виявляється так:
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 мають таку ж ймовірність, але все ще є невеликий ухил до 0, отже, 0 все-таки був переможцем у вашому тесті зі 100 000 ітерацій.
Щоб виправити зміщення модуля, спочатку слід спростити формулу (якщо ви хочете лише 0-5, то модуль дорівнює 6, а не 3600 або навіть більш божевільне число, в цьому немає сенсу). Саме таке спрощення значно зменшить ваш ухил (32766 карт до 0, 32767 до 1, що надасть крихітні зміщення цим двом числам).
Щоб взагалі позбутися від упередженості, вам потрібно перезапустити (наприклад), коли $RANDOM
він нижчий 32768 % 6
(усунути стани, які не відображають ідеально до наявного випадкового діапазону).
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
Результати тесту:
16425 5
16515 1
16720 0
16769 2
16776 4
16795 3
Альтернативою було б використання іншого випадкового джерела, яке не має помітного зміщення (порядків більше, ніж лише 32768 можливих значень). Але реалізація логіки перезавантаження все одно не зашкодить (навіть якщо це, швидше за все, ніколи не здійсниться).