การสุ่มตัวเลขในภาษา Python
ในบทนี้ คุณจะได้เรียนรู้เกี่ยวกับการสุ่มตัวเลขในภาษา Python เราจะแนะนำให้คุณรู้จักกับฟังก์ชันในไลบรารี่มาตรฐานของภาษาที่ใช้สำหรับการสุ่มตัวเลขแบบต่างๆ ในภาษา Python นี่เป็นเนื้อหาในบทนี้
- การสุ่มตัวเลขจำนวนเต็ม
- การสุ่มตัวเลขทศนิยม
- Random seed
- การสุ่มตัวเลขแบบ CPRNG
การสุ่มตัวเลข คือการสร้างตัวเลขขึ้นมาแบบสุ่มด้วยวิธีการทางคอมพิวเตอร์เพื่อนำมาใช้งานในโปรแกรม มันมีประโยชน์เมื่อเราต้องการเขียนโปรแกรมที่มีการทำงานแบบสุ่ม เช่น การทอยลูกเต๋า การสับไพ่ หรือการสุ่มสิ่งของในเกม ในภาษา Python นั้นมีโมดูล random
ที่ประกอบไปด้วยฟังก์ชันสำหรับสุ่มตัวเลขแบบต่างๆ ที่ใช้อัลกอริทึม Pseudorandom number generator (PRNG) สำหรับสุ่มตัวเลข
การสุ่มตัวเลขจำนวนเต็ม
การสุ่มตัวเลขจำนวนเต็มเป็นรูปแบบการสุ่มตัวเลขที่พบบ่อยที่สุดในการเขียนโปรแกรม สำหรับตัวอย่างแรกในบทนี้ เรามาเขียนโปรแกรมสำหรับสุ่มตัวเลขจำนวนเต็มอย่างง่ายและแสดงผลตัวเลขที่สุ่มได้ออกทางหน้าจอ นี่เป็นตัวอย่าง
from random import randint, getrandbits
# Random integers between 1 - 10
print(randint(1, 10))
print(randint(1, 10))
# 4 bits-sized integers
print(getrandbits(8))
print(getrandbits(8))
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
1
3
28
197
ในตัวอย่าง เราได้แนะนำสองฟังก์ชันสำหรับสุ่มตัวเลขจำนวนเต็มในภาษา Python ฟังก์ชันเหล่านี้เป็นฟังก์ชันจากโมดูล random
ดังนั้นเราได้ทำการ import เข้ามาในโปรแกรมก่อนใช้งาน ทั้งสองฟังก์ชันนั้นใช้สำหรับสุ่มตัวเลขจำนวนเต็มเหมือนกัน แต่มีการทำงานที่แตกต่างกันดังนี้
print(randint(1, 10))
ฟังก์ชัน randint()
ใช้สำหรับสุ่มตัวเลขจำนวนเต็มจากช่วงของพารามิเตอร์ที่กำหนด ในตัวอย่างเป็นการสุ่มตัวเลขที่มีค่าระหว่าง 1 - 10
คุณสามารถระบุช่วงของตัวเลขใดๆ ที่ต้องการสุ่มได้
print(getrandbits(8))
ฟังก์ชัน getrandbits()
ใช้สำหรับสุ่มตัวเลขที่มีขนาดตามจำนวนบิตที่กำหนด ในตัวอย่างเป็นการสุ่มตัวเลขที่มีขนาด 8 บิต นั่นหมายความว่าค่าที่เป็นไปได้ของการสุ่มจะอยู่ระหว่าง 0 - 255
มาดูตัวอย่างเพิ่มเติมสำหรับการสุ่มตัวเลขจำนวนเต็ม ในตัวอย่างนี้เป็นการสุ่มตัวเลขระหว่าง 1 - 100 จากนั้นเก็บเข้าใน List และนำมาหาผลรวมและค่าเฉลี่ยของตัวเลขภายในลิสต์ และแสดงผลออกทางหน้าจอ นี่เป็นตัวอย่าง
from random import randint
numbers = []
print("Random numbers:")
for i in range(10):
n = randint(1, 100)
print(n, end =' ')
numbers.append(n)
s = sum(numbers)
a = s / len(numbers)
print("\nSum = %d" % s)
print("Average = %f" % a)
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Random numbers:
58 8 73 82 85 6 9 19 27 19
Sum = 386
Average = 38.600000
ในตัวอย่าง เป็นโปรแกรมสำหรับสุ่มตัวเลขจาก 1 - 100 เป็นจำนวน 10 ตัวเลขและเก็บไว้ในลิสต์ ในตอนแรกเราได้ประกาศตัวแปรลิสต์ numbers
สำหรับเก็บตัวเลขทั้งหมดที่จะได้มาจากการสุ่ม
for i in range(10):
n = randint(1, 100)
print(n, end =' ')
numbers.append(n)
เราใช้คำสั่งวนซ้ำ for loop สำหรับวนสุ่มตัวเลขที่มีค่าระหว่าง 1 -100 จากนั้นเก็บเข้าไปในตัวแปรลิสต์ด้วยเมธอด append()
นอกจากนี้เรายังแสดงตัวเลขที่สุ่มมาได้ภายในลูปเพื่อแสดงการทำงานของตัวเลขที่สุ่มได้ในแต่รอบ
s = sum(numbers)
a = s / len(numbers)
จากนั้นนำมาตัวเลขที่สุ่มได้ในลิสต์มาหาผลรวมด้วยฟังก์ชัน sum()
และหาค่าเฉลี่ยของตัวเลขจากผลรวมหารด้วยจำนวนของตัวเลขทั้งหมดและแสดงผลลัพธ์ที่ได้ออกทางหน้าจอ
การสุ่มตัวเลขทศนิยม
ในตัวอย่างก่อนหน้าคุณได้เรียนรู้การสุ่มตัวเลขจำนวนเต็มในภาษา Python ซึ่งนั่นเป็นกรณีการใช้งานทั่วไปในการเขียนโปรแกรม อย่างไรก็ตามในบางกรณี คุณอาจต้องการสุ่มตัวเลขทศนิยมเพื่อนำมาใช้ในโปรแกรม ในตัวอย่างนี้ เราจะแนะนำฟังก์ชันที่ใช้สำหรับสุ่มตัวเลขทศนิยมในภาษา Python
นี่เป็นตัวอย่างของโปรแกรมที่สุ่มตัวเลขทศนิยมจากช่วงต่างๆ ในภาษา Python โดยการใช้ฟังก์ชันจากไลบรารี่มาตรฐาน random
from random import random, uniform
# Random numbers between [0.0, 1.0)
print(random())
print(random())
# Random numbers between [0.0, 20.0]
print(uniform(0, 20))
print(uniform(0, 20))
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
0.2312618740781729
0.6039213323707252
13.375267975292829
6.3944059358623555
ในตัวอย่างนี้ แนะนำให้คุณรู้จักกับสองฟังก์ชันที่ใช้สำหรับสุ่มตัวเลขจำนวนจริงในภาษา Python ฟังก์ชันเหล่านี้อยู่ในไลบรารี่ random
ดังนั้นเราทำการ import มันเข้ามาก่อนการใช้งานในโปรแกรม
print(random())
ฟังก์ชัน random()
ใช้สำหรับสุ่มตัวเลขที่มีจาก 0.0
แต่ไม่เกิน 1.0
นั่นหมายความว่าค่าที่ได้จากการสุ่มจะมีช่วงอยู่ระหว่าง 0.0 - 0.9999...
นี่เป็นฟังก์ชันพื้นฐานที่ใช้ในการสุ่มตัวเลขทุกแบบในภาษา Python
print(uniform(0, 20))
ส่วนฟังก์ชัน uniform()
นั้นใช้สำหรับสุ่มตัวเลขทศนิยมจากช่วงที่กำหนด ในตัวอย่างเราใช้มันสำหรับสุ่มตัวเลขที่มีค่าอยู่ระหว่าง 0.0 - 20.0
สำหรับฟังก์ชัน uniform()
นั้นผลลัพธ์ที่ได้จากการสุ่มจะรวมกับพารามิเตอร์ที่สองเสมอ
Random seed
ฟังก์ชันสุ่มตัวเลขพื้นฐานในภาษา Python ใช้อัลกอริทึม Pseudorandom number generator (PRNG) เป็นวิธีการสุ่มหลัก ซึ่งอัลกอริทึม PRNG นั้นใช้สมการทางคณิตศาสตร์สำหรับสร้างลำดับของตัวเลขในการสุ่ม และมันใช้ Random seed ในการกำหนดการทำงาน
Random seed คือตัวเลขที่ใช้กำหนดการทำงานของตัวสุ่มตัวเลข โดยปกติแล้วเราจะต้องกำหนด Random seed ให้กับตัวสุ่มก่อนเสมอ อย่างไรก็ตามในภาษา Python ได้ทำขั้นตอนนี้ให้อัติโนมัติ โดยใช้ค่าใช้ที่เปลี่ยนไปตลอดเวลา เช่น ค่า Timestamp ปัจจุบันของระบบ ดังนั้นเราไม่จำเป็นต้องกำหนดมันด้วยตัวเอง
อย่างไรก็ตาม เราสามารถกำหนดค่า Random seed ด้วยตัวเองได้หากต้องการ โดยการใช้ฟังก์ชัน seed()
นี่จะทำให้เราสามารถควบคุมลำดับของตัวเลขจากการสุ่มได้ สิ่งหนึ่งที่ต้องเข้าใจเกี่ยวกับ Random seed สำหรับค่าของ Random seed ใดๆ นั้นจะให้ลำดับการสุ่มตัวเลขแบบเดิมเสมอ นี่เป็นตัวอย่าง
from random import seed, randint
seed(12)
for i in range(10):
print(randint(1, 100), end = " ")
ในตัวอย่าง เป็นการใช้ฟังก์ชัน seed()
ในการกำหนดค่า Random seed ให้กับโปรแกรมเพื่อทำงาน เนื่องจากค่าของ Random seed นั้นถูกกำหนดไว้เป็น 12
เสมอ ดังนั้นเมื่อโปรแกรมถูกรันลำดับของตัวเลขที่สุ่มได้จะเป็นเหมือนเดิมเสมอ นี่เป็นผลลัพธ์การทำงานของโปรแกรมจากการรันสองครั้ง
61 35 85 68 86 45 19 49 2 48
61 35 85 68 86 45 19 49 2 48
จะเห็นว่าไม่ว่าเราจะรันโปรแกรมกี่ครั้งกับค่า Random seed ที่มีค่าเป็น 12
ลำดับของการสุ่มจะยังคงเป็นเหมือนเดิมเสมอ นั่นหมายความว่าทุกๆ ค่าของ Random seed จะมีลำดับการสุ่มที่ตายตัวเสมอ ซึ่งนี่เป็นวิธีการทำงานพื้นฐานของ PRNG
เพื่อทำให้ลำดับของการสุ่มแตกต่างกัน เราจะต้องกำหนดค่า Random seed ที่แตกต่างกันออกไปในการรันโปรแกรมแต่ละครั้ง ซึ่งนี่สามารถทำได้โดยการใช้เวลา Timestamp เป็น Random seed ซึ่งนี่เองเป็นวิธีที่ Python ทำให้กับเราอัตโนมัติเมื่อเราไม้ได้กำหนดค่า Random seed ให้กับโปรแกรม
from random import seed, randint
from datetime import datetime
seed(datetime.now().microsecond)
for i in range(10):
print(randint(1, 100), end = " ")
นี่เป็นผลลัพธ์การทำงานของโปรแกรมจากการรันสองครั้ง
83 47 39 85 97 42 18 46 45 34
54 59 31 17 7 39 87 71 25 62
ในตัวอย่าง เราได้กำหนดค่า Random seed ด้วยเวลา Timestamp ที่รับค่ามาจากฟังก์ชัน datetime.now()
ในไลบรารี่ datetime
ดังนั้นเมื่อรันโปรแกรมในแต่ละครั้งผลลัพธ์ของการสุ่มนั้นจะแตกต่างกัน เนื่องจาก Timestamp ในขณะที่รันแตกต่างกันนั่นเอง
การสุ่มตัวเลขแบบ CPRNG
Pseudorandom number generator (PRNG) เป็นวิธีพื้นฐานสำหรับการสุ่มตัวเลข แต่มันอาจไม่เหมาะสำหรับทุกวัตถุประสงค์ เพราะการสุ่มนั้นถูกกำหนดการทำงานด้วย Random seed และลำดับของการสุ่มง่ายต่อการคาดเดา ดังนั้นถ้าหากใครบางคนสามารถจำลำดับการสุ่มของ Random seed = 12 ได้ มันเป็นไปได้ที่เขาจะรู้ว่าตัวเลขถัดไปจากการสุ่มจะเป็นอะไร
อีกวิธีหนึ่งของการสุ่มตัวเลข; Cryptographically secure pseudorandom number generator (CPRNG) เป็นการสุ่มที่ปลอดภัยด้วยวิธีการเข้ารหัสทางคอมพิวเตอร์ โดยใช้เอนโทรปีที่ได้รับจากแหล่งคุณภาพสูง เช่น จากระบบปฏิบัติ การสุ่มด้วยวิธีนี้จะไม่ขึ้นอยู่กับ Random seed และเป็นการสุ่มที่เหมือนกับการสุ่มในธรรมชาติ เช่น การทอยลูกเต๋า หรือการสับไพ่ เป็นต้น ดังนั้นเมื่อโปรแกรมของคุณต้องการการสุ่มที่มีความปลอดภัยและไม่สามารถคาดเดาได้ เราแนะนำให้ใช้การสุ่มแบบ CPRNG
ในภาษา Python มีฟังก์ชันในโมดูล secrets
สำหรับสุ่มตัวเลขแบบ CPRNG ในการใช้งานฟังก์ชันนี้เพื่อสุ่มตัวเลข ค่าทีี่ได้จากการสุ่มแต่ละครั้งจากการเรียกฟังก์ชันจะเป็นอิสระต่อกัน และไม่สามารถคาดเดาได้เนื่องจากมันไม่ขึ้นกับ Random seed นั่นเอง นี่เป็นตัวอย่างการใช้งาน
from secrets import randbelow, randbits
# Random numbers 0 - 9
print(randbelow(10))
print(randbelow(10))
# 4 bits-sized integers (0 - 255)
print(randbits(8))
print(randbits(8))
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
4
8
215
122
ในตัวอย่าง เป็นการใช้งานสองฟังก์ชันสำหรับสุ่มตัวเลขจำนวนเต็มด้วยวิธึ CPRNG นี่ทำให้ค่าที่ได้จากการสุ่มในแต่ละครั้งไม่ขึ้นต่อกัน และเป็นการสุ่มที่เหมือนกับที่เกิดขึ้นในธรรมชาติ
print(randbelow(10))
ฟังก์ชัน randbelow()
ใช้สำหรับสุ่มตัวเลขจำนวนเต็มที่มีค่าจาก 0 และไม่เกินค่าของพารามิเตอร์ ในตัวอย่างเป็นการใช้ฟังก์ชันเพื่อสุ่มตัวเลขจาก 0 - 9
สองครั้ง
print(randbits(8))
ฟังก์ชัน randbits()
ใช้สำหรับสุ่มตัวเลขที่มีขนาดตามจำนวนบิตที่กำหนด ในตัวอย่างเป็นการสุ่มตัวเลขที่มีขนาด 8 บิต นั่นหมายความว่าค่าที่เป็นไปได้ของการสุ่มจะอยู่ระหว่าง 0 - 255
สำหรับตัวอย่างสุดท้ายในบทนี้ มาดูตัวอย่างของโปรแกรมในการทอยลูกเต๋า โดยการใช้ฟังก์ชันการสุ่มจากโมดูล secrets
นี่เป็นโค้ดของการทำงานของโปรแกรม
from secrets import randbelow
from time import sleep
print("Rolling dice...")
time = 320
for i in range(8):
n = randbelow(6) + 1
print("\r%d" % n, end = "")
sleep(time / 1000)
time = time - 40
print("\nDone")
นี่เป็นผลลัพธ์การทำงานของโปรแกรม ซึ่งการรันโปรแกรมนั้นเปรียบเสมือนกับการที่เราทอยลูกเต๋าจริงๆ
Rolling dice...
3
Done
ในตัวอย่าง เป็นโปรแกรมสำหรับจำลองการทอยลูกเต๋าที่เหมือนกับการทอยลูกเต๋าจริงๆ โดยโปรแกรมได้แสดงแอนิเมชันระหว่างการทอยก่อนที่จะได้ค่าของการทอยจริงๆ ด้วย
for i in range(8):
...
เพืื่อแสดงแอนิเมชันของการทอยลูกเต๋า เราใช้คำสั่ง for loop ในการสุ่มตัวเลขเป็นจำนวน 8 ครั้งและแสดงมันออกทางหน้าจอ สำหรับการแสดงครั้งถัดไปเราได้ลบการแสดงครั้งก่อนหน้าออกไป ด้วยตัวอักษรพิเศษ \r
ที่กำหนดในฟังก์ชัน print()
sleep(time / 1000)
time = time - 40
ก่อนการแสดงแอนิเมชันในเฟรมถัดไป เราได้หยุดการทำงานของโปรแกรมเป็นเวลา 320 มิลลิวินาที และลดลงทีละ 40 มิลลิวินาทีในแต่ละรอบ ซึ่งรอบสุดท้ายของการสุ่มคือการค่าที่ได้จากการทอยจริงๆ
n = randbelow(6) + 1
เนื่องจากลูกเต๋านั้นมี 6 หน้า ดังนั้นเราใช้ฟังก์ชัน randbelow()
ในการสุ่มตัวเลขจำนวนเต็มจาก 1 - 6
ซึ่งหมายถึงแต่ละหน้าของลูกเต๋า
ในบทนี้ คุณได้เรียนรู้เกี่ยวกับการสุ่มตัวเลขในภาษา Python เราได้พูดถึงการใช้ฟังก์ชันสำหรับสุ่มตัวเลขในรูปแบบต่างๆ การสุ่มแบบ PSRNG ซึ่งเป็นวิธีการสุ่มพื้นฐานที่ใช้ Random seed ในการสุ่ม และการสุ่มตัวเลขแบบ CPRNG สำหรับการสุ่มตัวเลขแบบธรรมชาติ