คอมพิวเตอร์สุ่มเลขไม่เป็น

เรามีเรื่องให้ต้องสุ่มอยู่เสมอ อย่างการโยนลูกเต๋าเวลาเล่นบอร์ดเกม กรรมการกีฬาที่โยนเหรียญเพื่อหาว่าทีมไหนได้เริ่มก่อน หรือหวยเองก็เป็นการสุ่ม ซึ่งการสุ่มเลขขึ้นมาสักตัวนั้นไม่ยากสำหรับมนุษย์ แต่ยากมากสำหรับคอมพิวเตอร์ ซึ่งบางคนอ่านแล้วอาจจะเถียงในใจว่า
“ไม่จริงหรอกคอมพิวเตอร์สุ่มได้ เวลาเล่นบอร์ดเกมออนไลน์ หรือเวลาสุ่มเพลงในแอปฟังเพลงไง”
บทความนี้เราเลยจะมาคุยกันว่า ที่จริงแล้วคอมพิวเตอร์มันไม่เคยสุ่ม และที่เราเคยเห็นว่ามันสุ่ม มันไม่ได้สุ่มจริง ๆ เลยสักครั้ง
แล้วการสุ่มคืออะไรกันแน่ละ
สาเหตุที่เรามองว่าการโยนเหรียญนั้นสุ่ม เพราะเราไม่รู้ว่ามันจะออกหัวหรือก้อยกันแน่ คือไม่ได้มานั่งคำนวนว่าเหรียญที่หลุดออกไปจากมือเราด้วยความเร็วเท่านี้องศาเท่านี้นั้นมันจะตกลงพื้นหน้าไหน เราแค่ออกแรงไป “มั่ว ๆ” เท่านั้นเอง และนั่นแหละคือสิ่งที่คอมพิวเตอร์ทำไม่ได้ เพราะคอมพิวเตอร์มั่วไม่เป็น คอมพิวเตอร์ออกแบบมาเพื่อทำงานแบบคาดเดาได้และคำนวนได้ สั่งให้บวกเลขก็ต้องบวกเลข และต้องบวกอย่างถูกต้อง ถ้าสั่งให้มันบวกเลขแล้วต้องลุ้นว่ามันจะทำอะไรให้เรานี่คอมน่าจะเสียแล้ว ซึ่งตรงกันข้ามกันเลยกับการสุ่มที่ไม่ควรถูกคาดเดาหรือคำนวนได้
ดังนั้นเวลาเราสั่งให้คอมพิวเตอร์สุ่ม สิ่งที่คอมพิวเตอร์ทำมันคืออะไรกันแน่
สิ่งที่คอมพิวเตอร์ทำคือการพยายามเลียนแบบการสุ่ม ด้วยสมการบางอย่างที่ความจริงแล้วสามารถคำนวณได้ สิ่งนี้เรียกว่าการสร้างเลขสุ่มเทียม (Pseudo Random Number Generator, PRNG) ซึ่งการสุ่มที่มาจากคอมพิวเตอร์นั้นเป็นการสุ่มเทียมแทบทั้งสิ้น
นึกถึงเวลาเราเขียนโปรแกรมแล้วสั่งให้มันสร้างเลขสุ่ม เราจะต้องกำหนด seed ซึ่งคือค่าที่กำหนดว่าจะทำให้การสุ่มออกมาเป็นแบบไหน หากว่าผู้เขียนโปรแกรมใส่ seed เดิมแล้วรันโปรแกรม เลขที่สุ่มออกมาจะเป็นเลขเดิมตลอดเสมอ หรือถ้าใครที่เคยเล่นเกม Minecraft ตอนสร้างโลกใหม่ เกมมันจะมีช่องให้ใส่ seed ซึ่งค่า seed นี่แหละถูกเอาใช้ในการคำนวนเลขสุ่ม ไปลองดูก็ได้ ว่าถ้าใส่ seed เดิม เราก็จะได้โลกที่เหมือนเดิมทุกครั้ง
PRNG ที่ดีควรจะมีสมบัติที่สำคัญ 2 ข้อ
ข้อแรก เลขที่สุ่มออกมาต้องกระจายตัวอย่างสม่ำเสมอ คือต้องไม่สุ่มออกมาแล้วได้เลขบางตัวเยอะเป็นพิเศษ อย่างในรูปข้างล่างจะเห็นว่า PRNG ที่สร้างเลขสุ่มในรูปซ้ายนั้นดูดีกว่า PRNG ที่สร้างเลขสุ่มในรูปขวา

และข้อสอง คือคาบของการสุ่มควรจะยาวที่สุดเท่าที่จะยาวได้ คือเนื่องจาก PRNG นั้นไม่ได้สุ่มจริง ๆ ดังนั้นเมื่อสุ่มไปเรื่อย ๆ มันจะวนกลับมาที่จุดเริ่มต้นใหม่ และสุ่มได้เลขชุดเดิมเป้ะเลย เรียกว่าครบ 1 คาบ ดังนั้นหากความยาวของ 1 คาบมันสั้นเกินไป เลขสุ่มที่ได้นั้นจะถูกคาดเดาได้ง่าย
หนึ่งใน PRNG ที่พื้นฐานที่สุดเรียกว่า ตัวสร้างเลขสุ่มเชิงเส้น (Linear Congruential Generator, LCG) ซึ่งสร้างเลขสุ่มจากสมการ
เมื่อค่า m, a และ c เป็นค่าคงที่ที่กำหนดขึ้น เช่นถ้าเราใช้ m = 9, a = 4 และ c =1 โดยกำหนดค่าเริ่มต้นหรือ seed ให้เท่ากับ 0 แล้วคำนวณตามสมการจะได้
1 = (4 × 0 + 1) mod 9
ซึ่ง 1 ก็คือเลขตัวแรกที่เราสุ่มมาได้ จากนั้นก็เอา 1 ไปแทนค่าแล้วสร้างเลขถัดไป จะได้
5 = (4 × 1 + 1) mod 9
และเมื่อทำแบบนี้ไปเรื่อย ๆ เราจะได้ชุดของเลขสุ่มเทียมออกมาเป็น 0 1 5 3 4 8 6 7 2 0 1 แล้วหลังจากนั้นมันก็จะเริ่มวนกลับมาเป็น 5 3 4 ... อีกรอบแล้ว
จะเห็นว่าการใช้ m = 9, a = 4, c =1 และ seed = 0 นั้นทำให้เราเลขสุ่มเทียมที่คาบเท่ากับ 9 และกระจายตัวกันดี แต่หากเราใช้ m = 9, a = 2, c = 0 และ seed = 3 เราจะได้ชุดเลขสุ่มคือ 6 3 6 3 6 ... ซึ่งมีคาบเท่ากับ 2 เท่านั้น
เห็นได้ชัดว่าว่าการกำหนดตัวแปร m, a, c และ seed ให้ดีนั้นสำคัญมาก เพราะมันมีผลต่อทั้งคาบและความกระจายตัวของเลขสุ่มเทียมที่ได้
ด้วยความดูง่ายของมัน คุณอาจจะเผลอคิดไปว่า LCG คงเป็น PRNG ที่ไม่ได้ถูกใช้จริง และเป็นแค่ตัวอย่างแรก ๆ ในหนังสือเรียนเท่านั้น แต่เปล่าเลย LCG ยังถูกใช้จนถึงปัจจุบัน และยังถูกใช้ในหลายคอมไพเลอร์ของภาษา C เนื่องจากการสร้าง LCG นั้นทำได้ง่าย ทำงานได้เร็ว และใช้ความจำไม่เยอะ
ในปัจจุบันมีวิธีการใหม่อื่น ๆ ที่ลดความสำคัญของการกำหนดตัวแปรทั้งหลายลง แต่ยังดึงประโยชน์ของความเรียบง่ายของ LCG มาด้วย ใครที่สนใจเพิ่มเติมสามารถไปศึกษาต่อได้ในลิงก์ที่แปะไว้ให้ท้ายบทความ
ในทางปฏิบัติ เพื่อไม่ให้ผลที่ได้จากการสุ่มเลขออกมาเหมือนเดิมทุกรอบ เราอาจจะเลือก seed วันที่และเวลา ณ ตอนนั้น เพราะจะได้ใช้ seed ที่ไม่เหมือนกันในแต่ละครั้งที่รันโปรแกรม แต่การใช้วันที่และเวลาก็อาจจะคาดเดาได้ง่ายเกินไปซึ่งเป็นอันตราย โดยเฉพาะในบริบทที่เลขสุ่มที่สร้างนั้นจะไปมีสำคัญต่อความปลอดภัยของผู้ใช้ เช่นการเข้ารหัสข้อความ
จึงมีคนเสนอวิธีการที่จะสร้าง seed ที่คาดเดายากขึ้นมากกว่าการใช้วันที่ เช่นเว็บไซต์ random.org ที่ใช้ความแปรปวนในชั้นบรรยากาศมาสร้างเลขสุ่ม เพราะคนที่ได้เลขสุ่มมาก็คงไม่รู้ว่าความแปรปวนในชั้นบรรยากาศเป็นอย่างไร ณ เวลานั้น หรือ getrandom ซึ่งเป็นคำสั่งสร้างเลขสุ่มที่มาพร้อมกับระบบปฏิบัติการ Linux ที่จะสร้างเลขสุ่มจากการกระทำต่าง ๆ ที่เกิดขึ้นภายในคอมพิวเตอร์เช่นการขยับเมาส์หรือพิมพ์คีย์บอร์ด
สรุปก็คือ คอมพิวเตอร์ไม่สามารถสร้างเลขสุ่มจริง ๆ ได้ เพราะมันทำงานตามหลักตรรกะและสมการทางคณิตศาสตร์ ดังนั้นเราจึงต้องสร้างสมการคณิตศาสตร์ขึ้นมาเพื่อให้คอมพิวเตอร์สามารถสร้างเลขสุ่มเทียม ที่เลียนแบบการสุ่มได้ดีพอสำหรับการใช้งานทั่วไป ซึ่งแม้ว่ามันจะไม่ใช่การสุ่มแท้ ๆ แบบธรรมชาติ แต่ในบริบทการใช้งานทั่วไป การสุ่มเทียมก็เพียงพอและมีประสิทธิภาพมากพอแล้ว
และเช่นเดิม ใครที่อยากสนับสนุนเพจเว็บไซต์ของเรา ให้ผลิตคอนเทนต์คณิตศาสตร์แบบนี้ต่อไป ก็สามารถสมัครเป็นสมาชิกรายเดือนได้โดยกดปุ่ม 'สมัครสมาชิก' ได้เลยนะฮะ
เอกสารอ้างอิง
https://www.geeksforgeeks.org/pseudo-random-number-generator-prng/
https://link.springer.com/referenceworkentry/10.1007/0-387-23483-7_231
https://www.cs.hmc.edu/tr/hmc-cs-2014-0905.pdf
https://man7.org/linux/man-pages/man7/random.7.html
https://lwn.net/Articles/261804/
https://www.random.org/
https://www.youtube.com/watch?v=UtNXUMrSIxQ