สุ่มยุติธรรมไหม
สั้น ๆ คือยุติธรรม ส่วนที่ยาวกว่าอยู่ด้านล่าง พร้อมตัวเลขให้คุณตรวจเองได้
ตัวสุ่มมาจากไหน
ผลทุกครั้งมาจาก crypto.getRandomValues ตัวสุ่มสำหรับงานเข้ารหัสที่เบราว์เซอร์มีให้ ซึ่งดึงความสุ่มจากระบบปฏิบัติการ รู้ผลครั้งก่อนทั้งหมดก็ยังทายครั้งถัดไปไม่ได้
soom ไม่ใช้ Math.random ตัดสินผล ตัวนั้นใช้แค่กับของประดับ เช่น ตัวอักษรที่กลิ้งบนป้ายพลิกระหว่างรอ หรือเสียงที่เพี้ยนนิด ๆ ให้ไม่น่าเบื่อ
แต่ละครั้งได้ตัวเลข 32 บิต คือจำนวนเต็มตั้งแต่ 0 ถึง 4,294,967,295 แล้วจึงแปลงเป็นตัวเลือกของคุณ ขั้นแปลงนี้แหละที่เว็บสุ่มส่วนใหญ่ทำพลาดโดยไม่รู้ตัว
ความลำเอียงจากการหารเอาเศษ
วิธีที่ง่ายที่สุดคือเอาเลขสุ่มไปหารด้วยจำนวนตัวเลือกแล้วใช้เศษ แต่ถ้าจำนวนเลขทั้งหมดหารด้วยจำนวนตัวเลือกไม่ลงตัว ตัวเลือกแรก ๆ จะได้เปรียบ เรียกว่า modulo bias
ย่อให้เห็นภาพ ถ้าตัวสุ่มให้เลข 0 ถึง 9 แค่สิบแบบ และคุณมี 3 ตัวเลือก เศษ 0 มาจาก 0, 3, 6, 9 สี่แบบ ส่วนเศษ 1 กับ 2 ได้แค่สามแบบ ตัวเลือกแรกจึงได้โอกาส 40% แทนที่จะเป็น 33.3%
กับเลข 32 บิตจริง ความต่างเล็กลงมาก แต่ไม่ใช่ศูนย์ และยิ่งรายการยาว ความต่างยิ่งมาก
soom แก้ยังไง
ใช้วิธีทิ้งแล้วสุ่มใหม่ (rejection sampling) หาจำนวนที่ใหญ่ที่สุดที่หารด้วยจำนวนตัวเลือกลงตัว ถ้าเลขที่สุ่มได้เกินจากนั้นก็ทิ้งแล้วสุ่มใหม่ เลขที่เหลือจึงแบ่งให้ทุกตัวเลือกได้เท่ากันพอดี
จากตัวอย่างเดิม ถ้าได้ 9 ก็ทิ้ง เหลือ 0 ถึง 8 ที่แบ่งให้สามตัวเลือกได้ตัวละสามแบบ ของจริงแทบไม่ต้องทิ้งเลย กับ 3 ตัวเลือกมีเลขที่ต้องทิ้งแค่ตัวเดียวจากกว่าสี่พันล้านตัว
// จำนวนเต็มตั้งแต่ 0 ถึง max - 1 โอกาสเท่ากันทุกตัว
function randInt(max) {
const limit = Math.floor(2 ** 32 / max) * max;
let x = random32(); // crypto.getRandomValues
while (x >= limit) x = random32();
return x % max;
}เรียงลำดับ แบ่งทีม และสุ่มหลายอัน
- เรียงลำดับใช้วิธี Fisher–Yates ที่หยิบทีละตำแหน่งจากตัวที่ยังเหลือ ทุกลำดับที่เป็นไปได้จึงมีโอกาสเท่ากัน ไม่ใช่แค่สลับไปมาไม่กี่ครั้ง
- แบ่งทีมสลับรายชื่อด้วยวิธีเดียวกันก่อน แล้วแจกทีละคนวนไปทุกทีม ทีมจึงต่างกันไม่เกินหนึ่งคน และใครเป็นคนที่เกินมาก็สุ่มเหมือนกัน
- สุ่มหลายอันพร้อมกันคือหยิบจากหัวรายการที่สลับแล้ว จึงไม่มีตัวไหนซ้ำ
- คัดออกคือการเรียงลำดับทั้งรายการไว้ก่อน แล้วค่อยเฉลยทีละรอบ ตัวสุดท้ายที่เหลือคือผล
แอนิเมชันไม่ได้ตัดสิน
ผลถูกสุ่มเสร็จตั้งแต่คุณกดปุ่ม ก่อนวงล้อเริ่มหมุน ก่อนลูกบอลกลิ้ง และก่อนคุณขูดบัตร สิ่งที่เห็นบนจอคือการเฉลยผลที่มีอยู่แล้ว กดแรงหรือเขย่าแรงแค่ไหนก็ไม่เปลี่ยนอะไร
ไพ่คว่ำก็เหมือนกัน ไพ่ทุกใบถูกสุ่มมาก่อนคุณเลือก ใบที่คุณเปิดจึงมีโอกาสเท่ากับใบอื่น
ชุดสำเร็จรูปที่มีหลายสิบคำตอบ เครื่องจะวาดแค่บางช่องให้อ่านออก แต่คำตอบถูกสุ่มจากทั้งชุด รายการของคุณเองที่ยาวเกิน 12 ก็เช่นกัน วงล้อเว้นช่องว่างไว้ แต่ทุกรายการยังมีโอกาสเท่ากัน
ทำไมออกซ้ำติดกันได้
การสุ่มที่ยุติธรรมไม่จำผลครั้งก่อน โยนเหรียญแล้วออกหน้าเดิมห้าครั้งติดมีโอกาส 1 ใน 32 ถ้าโยนกันทั้งห้องก็มีคนเจอแน่
ถ้าเครื่องสุ่มไหนพยายามไม่ให้ออกซ้ำ เครื่องนั้นแหละที่ไม่สุ่ม
ใครเปลี่ยนผลได้บ้าง
- ไม่มีเซิร์ฟเวอร์ไหนเลือกผล การสุ่มทั้งหมดเกิดในเบราว์เซอร์ของคุณ
- ผู้สนับสนุนมีแค่ชื่อบนหน้าจอและใบเสร็จ ไม่มีใครจ่ายเงินเพื่อให้ผลออกทางไหน
- รายการของคุณขึ้นเซิร์ฟเวอร์ก็ต่อเมื่อคุณกดส่งลิงก์สั้น หรือบันทึกชุดตอนเข้าสู่ระบบ รายละเอียดอยู่ในนโยบายความเป็นส่วนตัว