Random
為什麼我在使用 $RANDOM 時會得到分佈不均的結果?
我在Wikipedia上閱讀了有關 RNG和TLDP
$RANDOM
上的功能,但它並沒有真正解釋這個結果:$ max=$((6*3600)) $ for f in {1..100000}; do echo $(($RANDOM%max/3600)); done | sort | uniq -c 21787 0 22114 1 21933 2 12157 3 10938 4 11071 5
為什麼大約 2 倍以上的值比 3、4、5 更傾向於 0、1、2,但是當我更改最大模數時,它們幾乎均勻分佈在所有 10 個值上?
$ max=$((9*3600)) $ for f in {1..100000}; do echo $(($RANDOM%max/3600)); done | sort | uniq -c 11940 0 11199 1 10898 2 10945 3 11239 4 10928 5 10875 6 10759 7 11217 8
為了擴展模偏差的主題,您的公式是:
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 個可能值)。但是無論如何實施重滾邏輯並沒有什麼壞處(即使它可能永遠不會通過)。