หากต้องการขยายหัวข้อโมดูโลสูตรของคุณคือ:
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 ให้อคติเล็กน้อยกับตัวเลขทั้งสอง)
ในการกำจัดอคติโดยรวมคุณต้อง re-roll (ตัวอย่าง) เมื่อ$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) แต่การใช้ตรรกะ re-roll ต่อไปจะไม่ทำร้าย (แม้ว่ามันจะไม่เกิดขึ้นก็ตาม)