モジュロバイアスのトピックを展開するための式は次のとおりです。
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の確率の2倍になります。また、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にはわずかな偏りがあるため、テストでは100'000回の反復で0が勝者でした。
モジュロバイアスを修正するには、最初に式を単純化する必要があります(0〜5のみが必要な場合、モジュロは3600ではなく6であり、クレイジーな数でもありません)。この単純化だけで、バイアスが大幅に削減されます(32766は0にマップされ、32767は1にマップされ、これら2つの数値に小さなバイアスが与えられます)。
バイアスを完全になくすには、(たとえば)$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の可能な値よりも桁違いに大きい)。ただし、とにかく再ロールロジックを実装しても問題はありません(たとえたぶん実現しなかったとしても)。