จะสร้างตัวเลขสุ่มระหว่าง a และ b ใน Ruby ได้อย่างไร


189

เพื่อสร้างตัวเลขสุ่มระหว่าง 3 และ 10 ตัวอย่างเช่นฉันใช้: rand(8) + 3

มีวิธีที่ดีกว่าในการทำเช่นนี้rand(3, 10)หรือไม่?


4
def my_rand(x, y); rand(y - x) + x; end
Theo

@ Theo, y - x + 1โดยวิธีการ
Nakilon

1
ลองคำตอบที่ถูกต้องของคุณในวันที่ 10 และ 10 ** 24 ตามขีด จำกัด : 0 จะต้องรอนานมาก :)
Sayan Malakshinov

5
งานนี้:rand(3..10)
eikes

คำตอบ:


324

ปรับปรุง: ทับทิม 1.9.3 Kernel#randยังยอมรับช่วง

rand(a..b)

http://www.rubyinside.com/ruby-1-9-3-introduction-and-changes-5428.html

การแปลงไปเป็นอาร์เรย์อาจมีราคาแพงเกินไปและไม่จำเป็น


(a..b).to_a.sample

หรือ

[*a..b].sample

อาร์เรย์ # ตัวอย่าง

มาตรฐานใน Ruby 1.8.7+
หมายเหตุ: ชื่อ #choice ใน 1.8.7 และเปลี่ยนชื่อในรุ่นที่ใหม่กว่า

แต่อย่างไรก็ตามการสร้างอาเรย์ต้องการทรัพยากรและวิธีแก้ปัญหาที่คุณเขียนไปนั้นดีที่สุดคุณสามารถทำได้


ขอบคุณ! ฉันคิดว่าฉันจะอยู่กับเก่าและวิธีการที่ดี :)
Misha Moroshko

32
นี่เป็นความคิดที่แย่จริงๆโดยเฉพาะถ้า a และ b ของคุณมีขนาดที่ไม่รู้จัก ลอง (1000000000000000000000..100000000000000) .to_a.sample และดูว่าฉันหมายถึงอะไร
:)

4
@pearthearth หากคุณมีความคิดที่ดีกว่าซึ่งสอดคล้องกับคำถามคุณสามารถโพสต์ได้
Nakilon

rand(a..b)TypeError: can't convert Range into Integerไม่ได้ทำงานก็แยก: ยังไม่ได้รับการสนับสนุนในRuby 2.0
fguillen

2
@fguillen มันเหมาะกับฉันใน 1.9.3 ฉันไม่รู้ว่าทำไมมันถึงไม่เหมาะกับคุณ
Michael Dorst

87
Random.new.rand(a..b) 

aค่าต่ำสุดของคุณอยู่ที่ไหนและbเป็นค่าสูงสุดของคุณ


4
ข้อแตกต่างที่สำคัญที่ควรทราบคือหากคุณเพียงแค่โทรหาrand()คุณกำลังโทรหาKernel#randซึ่งสนับสนุนการmaxโต้แย้งเท่านั้น ถ้าคุณต้องการผ่านช่วงคุณต้องใช้Random#randหมายความว่าคุณต้องใช้วิธีนี้ +1
พอใจ

2
ควรเพิ่มที่กล่าวข้างต้นนำไปใช้กับ 1.9.2
grumpit

มันรวม a และ b หรือไม่?
Abhradip


11

เพียงสังเกตความแตกต่างระหว่างตัวดำเนินการช่วง:

3..10  # includes 10
3...10 # doesn't include 10

3

ดูคำตอบนี้ : มีใน Ruby 1.9.2 แต่ไม่ใช่ในเวอร์ชันก่อนหน้า โดยส่วนตัวฉันคิดว่าแรนด์ (8) +3 ใช้ได้ แต่ถ้าคุณสนใจลองคลาสสุ่มที่อธิบายไว้ในลิงค์




2

และนี่คือมาตรฐานที่รวดเร็วสำหรับทั้งสอง#sampleและ#rand:

irb(main):014:0* Benchmark.bm do |x|
irb(main):015:1*   x.report('sample') { 1_000_000.times { (1..100).to_a.sample } }
irb(main):016:1>   x.report('rand') { 1_000_000.times { rand(1..100) } }
irb(main):017:1> end
       user     system      total        real
sample  3.870000   0.020000   3.890000 (  3.888147)
rand  0.150000   0.000000   0.150000 (  0.153557)

ดังนั้นการทำrand(a..b)คือสิ่งที่ถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.