为了扩展模偏置的主题,您的公式是:
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个可能值)的其他随机源。但是无论如何,实施重新滚动逻辑不会有任何伤害(即使可能永远不会实现)。