Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การสร้างตัวเลขสุ่มใน Ruby

ตัวเลขสุ่มมีประโยชน์สำหรับวัตถุประสงค์ที่หลากหลาย เช่น ในการเล่นเกม การเข้ารหัส และการจำลองการสร้าง ในทางเทคนิค คอมพิวเตอร์ไม่สามารถสร้างตัวเลขสุ่มโดยการคำนวณเพียงอย่างเดียว เป็นไปไม่ได้โดยพื้นฐานแล้วที่จะสร้างตัวเลขสุ่มอย่างแท้จริงบนอุปกรณ์ที่กำหนดได้ สิ่งที่ดีที่สุดที่คุณหวังได้คือตัวเลขสุ่มเทียม ซึ่งเป็นกระแสของตัวเลขที่ปรากฏขึ้นราวกับสร้างขึ้นแบบสุ่ม

ในบทความนี้ เราจะมาดูวิธีต่างๆ ที่คุณสามารถสร้างตัวเลขสุ่มใน Ruby

การสร้างตัวเลขสุ่มด้วย Kernel#rand

เริ่มต้นด้วยการสร้างตัวเลขสุ่มด้วย rand กระบวนการ. เมื่อเมธอดถูกเรียกโดยไม่มีอาร์กิวเมนต์ จะส่งกลับค่าทศนิยมที่มากกว่าหรือเท่ากับ 0.0 และน้อยกว่า 1.0

rand()
> 0.7308136972953823

ในการรับจำนวนเต็ม คุณต้องส่งจำนวนเต็มไปยังฟังก์ชัน ฟังก์ชันจะคืนค่าจำนวนเต็มแบบสุ่มที่มากกว่าหรือเท่ากับ 0 และน้อยกว่าจำนวนเต็มที่ส่งไปยังฟังก์ชัน แต่ละครั้งที่เรียกใช้รายการต่อไปนี้ คุณจะได้รับตัวเลขที่อยู่ระหว่าง 0 ถึง 7

rand(8)
> 5

สำหรับตัวเลขสุ่มภายในช่วงที่กำหนด ให้ส่งช่วงไปที่ rand .

ต่อไปนี้ใช้ รวม ช่วงเพื่อสร้างตัวเลขสุ่มจากขีด จำกัด ล่าง (1 ) จนถึง (และรวมถึง) ขีดจำกัดบน (10 )

rand(1..10)
> 6

ตัวอย่างต่อไปใช้ ไม่รวม ช่วงเพื่อสร้างตัวเลขสุ่มจากขีดจำกัดล่าง จนถึง (แต่ไม่รวม) ขีดจำกัดบน

rand(1...10)
> 9

ช่วงสามารถอยู่ระหว่างค่าทศนิยมได้

rand(1.5..3.0)
> 1.7494305393711571

คุณยังสามารถใช้ขีดจำกัดช่วงค่าลบกับ rand .

rand(-5..-1)
> -5

การผ่านตัวเลขติดลบเดี่ยวอาจให้ผลลัพธ์ที่น่าประหลาดใจดังที่แสดงด้านล่าง

rand(-100)
> 94
 
rand(-0.5)
> 0.7692627344737486

นี่เป็นเพราะอาร์กิวเมนต์ n ส่งผ่านไปยัง rand , rand ส่งกลับตัวเลขสุ่มตั้งแต่ 0 ถึง (แต่ไม่รวม) n.to_i.abs . สำหรับตัวอย่างข้างต้น (-100).to_i.abs คือ 100 และ (-0.5).to_i.abs คือ 0 จึงเป็นผลลัพธ์ของตัวเลขสุ่ม

กำลังเรียก rand(0) คล้ายกับการเรียก rand() . คุณจะได้รับตัวเลขสุ่มระหว่าง 0.0 ถึง 1.0 (ไม่รวม)

กำลังสร้างลำดับที่ทำซ้ำได้ด้วย Kernel#srand

ก่อนจะไปสู่วิธีการสร้างตัวเลขสุ่มต่อไป มาดูที่ srand กันก่อน ฟังก์ชัน

Kernel#srand ตั้งค่า seed สำหรับ Kernel#rand . เราสามารถใช้มันเพื่อสร้างลำดับตัวเลขสุ่มซ้ำระหว่างการรันโปรแกรมต่างๆ ได้

เพื่อให้เข้าใจความหมาย ก่อนอื่นเราต้องเข้าใจวิธีการสร้างตัวเลขสุ่ม

สร้างตัวเลข "สุ่ม" จากเมล็ดพันธุ์

ตามที่ระบุไว้ก่อนหน้านี้ คอมพิวเตอร์ไม่ได้สร้างตัวเลขสุ่มอย่างแท้จริงจากการคำนวณ สิ่งที่พวกเขาทำคือสร้างลำดับของตัวเลขที่ดูเหมือนสุ่ม เมื่อต้องการทำเช่นนี้ คอมพิวเตอร์จะเริ่มต้นด้วยหมายเลขเมล็ดพันธุ์ ซึ่งจะทำงานผ่านอัลกอริธึมบางอย่าง จากนั้นจึงแยกเอาต์พุตที่ดูเหมือนสุ่มออกมา

คอมพิวเตอร์สร้างหมายเลขเมล็ดพันธุ์โดยใช้องค์ประกอบต่างๆ ผสมกัน เช่น เวลาประทับ ID กระบวนการของโปรแกรม ฯลฯ เนื่องจากองค์ประกอบเหล่านี้แตกต่างกันไปในแต่ละคำขอเพื่อสร้างหมายเลขสุ่ม หมายเลขเมล็ดพันธุ์จึงจะแตกต่างกันเสมอ ซึ่งจะสร้างลำดับตัวเลขที่แตกต่างกัน ดังนั้นผลลัพธ์ของตัวเลขสุ่มจึงออกมา หากคุณรันอัลกอริธึมด้วยเมล็ดพันธุ์เดียวกัน คุณจะได้ลำดับตัวเลขที่เหมือนกันในแต่ละครั้ง นี่คือสิ่งที่ Kernel#srand ทำให้เราทำได้

srand มักใช้ในการทดสอบ อาจเป็นประโยชน์สำหรับการทดสอบโค้ดในแอปของคุณที่เกี่ยวข้องกับการสุ่ม โดยมีค่าที่สุ่มแต่ยังคงคาดเดาได้มากพอที่จะทดสอบ นอกจากนี้ยังสามารถช่วยในการแยกหรือทำซ้ำจุดบกพร่อง

ด้านล่างเราใช้ srand เพื่อตั้งเมล็ดแล้วเรียก rand ขั้นแรกให้สร้างตัวเลขสุ่มสองสามตัว จากนั้นจึงสร้างลำดับของตัวเลขสุ่มสองชุด

srand(777)
 
rand()
> 0.152663734901322
 
rand()
> 0.3023566097075212
 
10.times.map { rand(10) }
> [7, 1, 7, 4, 7, 9, 8, 7, 2, 0]
 
10.times.map { rand(10) }
> [1, 2, 4, 5, 7, 1, 7, 2, 2, 7]

หากคุณเรียกใช้ srand อีกครั้งกับ seed เดิมและโทรเหมือนเดิม คุณจะเห็นว่าเราสุ่มหมายเลขเดียวกัน

srand(777)
 
rand()
> 0.152663734901322
 
rand()
> 0.3023566097075212
 
10.times.map { rand(10) }
> [7, 1, 7, 4, 7, 9, 8, 7, 2, 0]
 
10.times.map { rand(10) }
> [1, 2, 4, 5, 7, 1, 7, 2, 2, 7]

การสร้างตัวเลขสุ่มด้วยการสุ่ม

คุณยังสามารถสร้างตัวเลขสุ่มด้วยคลาสสุ่มได้

วิธีการเรียน rand จัดเตรียมฟังก์ชันพื้นฐานของ Kernel#rand ควบคู่ไปกับการจัดการค่าทศนิยมที่ดีขึ้น

Random.rand(1...10)
> 5

ไม่เหมือนกับ Kernel#rand , ถ้า Random.rand จะได้รับค่าลบหรือ 0 อาร์กิวเมนต์ มันทำให้เกิด ArgumentError

การสร้างตัวเลขสุ่มจากการแจกแจงแบบปกติ

ในโลกแห่งความเป็นจริง หลายสิ่งมักจะเป็นไปตามการกระจายแบบปกติ หากคุณมีช่วงของค่าบางอย่างที่อยู่ภายใต้ คุณจะไม่ค่อยได้รับการแจกแจงค่าทั้งหมดเท่าๆ กัน โดยส่วนใหญ่ ข้อมูลส่วนใหญ่มีแนวโน้มที่จะอยู่ในช่วงที่เล็กกว่า โดยมีเปอร์เซ็นต์ที่น้อยกว่าตกอยู่ในช่วงที่ใหญ่กว่า ยกตัวอย่างความสูงของผู้ชายที่เป็นผู้ใหญ่ ความสูงที่สั้นที่สุดที่บันทึกไว้คือ 54.6 ซม. (21.5 นิ้ว) ในขณะที่ส่วนสูงที่สุดคือ 267 ซม. (8'9") หากคุณต้องการสร้างข้อมูลเพื่อจำลองความสูงของผู้ชายในกลุ่มประชากร คุณอาจไม่ต้องการใช้ rand ด้วยข้อจำกัดเหล่านี้ คุณไม่ต้องการให้ความน่าจะเป็นที่จะได้ชาย 8'9" เท่ากับได้ชาย 6' เพราะแบบหลังเป็นเรื่องปกติมากกว่า

ตัวอย่างอื่นๆ ของสิ่งต่าง ๆ ที่ตามมาด้วยการแจกแจงแบบปกติคือ:

  • ข้อผิดพลาดในการวัด
  • ความดันโลหิต
  • คะแนนสอบ
  • น้ำหนักชาย/หญิงที่เป็นผู้ใหญ่

ในการสร้างตัวเลขสุ่มที่ดีขึ้นสำหรับกรณีการใช้งานดังกล่าว คุณสามารถใช้ rubystats พลอย

$ gem install rubystats
require 'rubystats'
 
adult_male_height = Rubystats::NormalDistribution.new(178, 10)
sample = 50.times.map { adult_male_height.rng.round(1) }
 
> [183.2, 169.5, 189.7, 171.9, 176.0, 179.3, 189.3, 175.3, 188.3, 190.0, 185.5, 182.8, 187.2, 191.6, 185.4, 178.4, 187.1, 183.3, 189.6, 179.7, 172.7, 174.4, 153.8, 197.4, 176.0, 174.6, 181.1, 182.0, 204.7, 185.2, 175.9, 167.7, 160.6, 170.5, 169.3, 160.6, 165.6, 166.4, 182.6, 179.7, 183.1, 171.9, 185.4, 175.4, 179.7, 176.9, 160.6, 173.8, 181.9, 190.2]

จากด้านบน เราส่งส่วนสูงเฉลี่ยสำหรับผู้ชาย (178 ซม.) และส่วนเบี่ยงเบนมาตรฐาน 10 ซม. ไปที่ NormalDistribution.new ก่อนสร้าง 50 ค่าที่อยู่ในการกระจายแบบปกตินี้ หากคุณอยากรู้เกี่ยวกับคณิตศาสตร์ บทความนี้อาจสนใจคุณ

สุ่มบทสรุป

นั่นนำเราไปสู่จุดสิ้นสุดของการสนทนานี้ เราได้กล่าวถึงวิธีต่างๆ ในการสร้างตัวเลข 'สุ่ม' ใน Ruby ด้วย rand , srand , Random และ Rubystats . นอกจากนี้เรายังได้กล่าวถึงวิธีการสร้างตัวเลข 'สุ่ม' โดยสังเขป และดูเหตุผลว่าทำไมอุปกรณ์ที่กำหนดไม่สามารถสร้างตัวเลขสุ่มที่แท้จริงได้

คุณควรทราบว่าวิธีการที่ครอบคลุมไม่เหมาะสำหรับกรณีการใช้งานทั้งหมดที่เรียกร้องให้มีการสุ่ม ตัวเลขจำนวนเต็มหรือทศนิยมที่สร้างขึ้นโดยวิธีการอาจเหมาะสำหรับการสร้างโอกาสในการเล่นเกมหรือสำหรับการสร้างแบบจำลอง แต่ในสถานการณ์ที่เรียกร้องให้มีความปลอดภัยบางอย่าง เช่น เมื่อสร้างโทเค็นการรีเซ็ตรหัสผ่าน คุณควรพิจารณาใช้ SecureRandom ด้วย SecureRandom คุณสามารถสร้างสตริงเลขฐานสิบหก ฐาน 64 ไบนารี และ UUID ที่ถอดรหัสได้ยากกว่ามากเมื่อเทียบกับตัวเลขธรรมดา

เราหวังว่าคุณจะพบสิ่งที่น่าสนใจนี้ หากคุณมีความคิดเห็นหรือคำถามเกี่ยวกับสิ่งที่เรากล่าวถึง โปรดติดต่อเราที่ @AppSignal คุณยังสามารถส่งคำขอของคุณสำหรับหัวข้อที่คุณต้องการได้

เราได้อัปเดตบทความนี้เมื่อวันที่ 1 สิงหาคม 2018 เพื่อรวมหมายเหตุเกี่ยวกับ SecureRandom