[TH] random

การสุ่มตัวเลขในภาษาไพธอนใช้คลาส random แต่ในระบบไมโครคอนโทรลเลอร์ไม่มีระบบที่สนับสนุนการสุ่มมากเหมือนในระบบคอมพิวเตอร์ทำให้ Micropython รองรับคำสั่งแตกต่างกันไปตามประเภทของชิพ โดยในบทความนี้กล่าวถึงการใช้ random กับไมโครคอนโทรลเลอร์ esp8266 และ esp32 ซึ่งมีคำสั่งให้ใช้งานเพียงสร้างตัวเลขสุ่ม และกำหนดค่า seed ของการสุ่มดังนี้

random

การสุ่มเป็นการสุ่มตัวเลขจำนวนเต็มโดยใช้การคำนวณจากค่า seed เป็นค่าเริ่มต้นในการสุ่ม ด้วยเหตุนี้ถ้ากำหนด seed เป็นตัวเลขเดียวกัน การสุ่มจะได้ค่าเหมือนกัน ดังตัวอย่างในส่วนของไมโครคอนโทรลเลอร์ esp8266 แต่ด้วยความแตกต่างของชิพ esp8266 และ esp32 ที่แตกต่างกัน ทำให้คลาาส random ของทั้งสองจึงแตกต่างกันไป คือ esp32 รองรับคำสั่งของ esp8266 แต่เพิ่มเติมคำสั่ง randrange, randint, choice, random และ uniform เข้ามา

esp8266

ไมโครคอนโทรลเลอร์ esp8266 รองรับคำสั่งการสุ่ม 2 คำสั่งดังภาพที่ 1 คือ ตั้งค่าการสุ่ม หรือ seed และทำการสุ่มตัวเลขจำนวนเต็มจำนวน n บิต

ภาพที่ 1 คลาส random ของ esp8266

การตั้งค่า seed ของการสุ่มใช้ตามรูปแบบการสั่งงานดังนี้

random.seed( ค่าสีด )

การสุ่มตัวเลขจำนวนเต็มต้องระบุจำนวนบิตของการสุ่ม ดังรูปแบบต่อไปนี้ เช่น ถ้าต้องการสุ่มค่าในช่วง 0-100 ต้องใช้ค่า n เป็น 7 เพราะรองรับการสุ่ม 0 ถึง 127 เป็นต้น

ค่าที่ได้ = random.getrandbits( n )

ตัวอย่างโปรแกรมของการใช้งานเป็นดัง demoRandom และตัวอย่างผลลัพธ์เป็นดังภาพที่ 2 จะพบว่า การตั้งค่า seed เป็นค่าเดียวกันทำให้ผลลัพธ์ของการสุ่มในแต่ละครั้งของการสุ่ม (สุ่มครั้งที่ n) ของตัวเลขมีค่เหมือนกัน

# demoRandom
import random

print("สุ่มตัวเลขขนาด 8 บิต")
for i in range(2):
    msg = "สุ่มครั้งที่ {} : ".format(i+1)
    for n in range(8):
        msg += str(random.getrandbits(8))
        msg += ","
    print(msg)
print("สุ่มตัวเลขขนาด 8 บิต ตั้ง seed เป็น 10")
for i in range(2):
    random.seed(10)
    msg = "สุ่มครั้งที่ {} : ".format(i+1)
    for n in range(8):
        msg += str(random.getrandbits(8))
        msg += ","
    print(msg)

ภาพที่ 2 ตัวอย่างผลลัพธ์จากการ demoRandom

esp32

คำสั่งในคลาส random ของ esp32 เป็นดังภาพที่ 3

ภาพที่ 3 คลาส random ของ esp32

การสุ่มตัวเลขทศนิยมในช่วง 0.0 ถึง 1.0 ใช้คำสั่งดังนี้

ค่าที่ได้ = random.random()

ถ้าต้องการสุ่มทศนิยมในช่วงค่าที่กำหนดให้ใช้คำสั่ง uniform ตามรูปแบบนี้

ค่าที่ได้ = random.uniform( ค่าเริ่ม, ค่าสิ้นสุด )

การสุ่มเลขตำนวนเต็มมี 2 รูปแบบคือ สุ่มในช่วงค่าที่กำหนด และสุ่มในช่วงค่าโดยระบุค่า step หรือค่าความห่างของเลขแต่ละชุดที่สสุ่มได้ เป็นดังนี้

ค่าที่ได้ = random.randint( ค่าเริ่ม, ค่าสิ้นสุด )
ค่าที่ได้ = random.ranrange( ค่าเริ่ม, ค่าสิ้นสุด, step )

สำหรับการสุ่มเลือกตัวเลือกจากข้อมูลแบบทูเพิลหรือลิสต์สามารถใช้คำสั่งต่อไปนี้เพื่อสุ่มเลือก

ค่าที่ได้ = random.choice( ตัวแปรลิสค์หรือทูเพิล )

ตัวอย่างโปรแกรม demoRandomEsp32 เป็นการใช้งานคำสั่งการสุ่มที่รองรับเฉพาะใน esp32 และตัวอย่างจากการรัน 2 ครั้งเป็นดังภาพที่ 4

# demoRandomEsp32
import random

print("random.random() ...............: {}".format(random.random()))
print("random.uniform(5,10) ..........: {}".format(random.uniform(5,10)))
print("random.randint(5,10) ..........: {}".format(random.randint(5,10)))
print("random.randrange(5, 20, 4) ....: {}".format(random.randrange(5, 20, 4)))

mcu = ("mcs51","pic","avr","stm32","esp8266","esp32")
print("random.choice(mcu) ............: {}".format(random.choice(mcu)))
ภาพที่ 4 ตัวอย่างผลลัพธ์จาก demoRandomEsp32

สรุป

จากบทความจะพบว่า การรองรับคำสั่งของคลาสในแต่ละไมโครคอนโทรลเลอร์นั้นมีความแตกต่างกัน และในแต่ละรุ่นของ Micripython อาจจะแตกต่างกันไปเช่นกัน เนื่องจากนักพัฒนาสามารถแก้ไขรหัสต้นฉบับของ Micropython หรือเขียนภาษา C เสริมการทำงานผ่านทาง cython ของภาษาไพธอนให้สามารถเรียกใช้ด้วยภาษาไพธอนได้ ดังนั้น เมื่อต้องพัฒนางานต้องตตรวจสอบให้แน่ใจก่อนว่าคำสั่งที่ต้องการนั้นรองรับด้วยตัวเลือกที่กำหนด และเช่นเดียวกัน ถ้าไม่ต้องการวิธีการสุ่มที่หลากหลาย การเลือกใช้ esp8266 ที่มีต้นทุนต่ำกว่าจึงเป็นทางเลือกที่น่าสนใจเช่นกัน ส่วนกรณีที่ต้องการสุ่มค่าและประมวลผลที่ซับซ้อน ทีมเราแนะนำให้ใช้ ulab เสริมเข้ามา สุดท้ายนี้ขอให้สนุกกับการเขียนโปรแกรมครับ

(C) 2020-2021, โดย อ.ดนัย เจษฎาฐิติกุล/อ.จารุต บุศราทิจ
ปรุบปรุงเมื่อ 2021-07-21, 2021-10-26