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


92

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

ดูเหมือนว่าarc4randomฟังก์ชันจะไม่มีอยู่อีกต่อไปเช่นเดียวกับarc4random_uniformฟังก์ชัน

ตัวเลือกที่ฉันมีอยู่arc4random_stir(), และarc4random_buf(UnsafeMutablePointer<Void>, Int) arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32)

ฉันไม่พบเอกสารใด ๆ ในฟังก์ชันและไม่มีความคิดเห็นในไฟล์ส่วนหัวที่ให้คำแนะนำ


3
ดูเหมือนว่าการเติมข้อความอัตโนมัติใน Xcode นั้นเพิ่งพัง ฉันสามารถสาบานได้ว่าฉันพิมพ์โดยไม่ต้องเติมข้อความอัตโนมัติและมันไม่ได้รวบรวม กำลังทำงานอยู่. ข้อมูลอ้างอิงที่ดีโดย @arsen
Big_Mac

1
arc4random_uniform สามารถใช้ได้ เป็นส่วนหนึ่งของ Foundation API ไม่ใช่ส่วนของภาษาดังนั้นคุณต้องมี "import Foundation" (หรือ "import UIKit") ที่ส่วนหัวของไฟล์เพื่อให้พร้อมใช้งาน
Vince O'Sullivan

ความน่าจะเป็น = Int (arc4random_uniform (UInt32 (ทั้งหมด))) - เนื่องจากหัวพิมพ์เสียการร้องเรียนในการพิมพ์จึงไม่เฉพาะเจาะจงนั่นคือข้อร้องเรียนในการคัดเลือกนักแสดงของฉันมาจากข้อผิดพลาดที่แตกต่างกันสองข้อ
bshirley

คำตอบ:


227

===== Swift 4.2 / Xcode 10 =====

let randomIntFrom0To10 = Int.random(in: 1..<10)
let randomFloat = Float.random(in: 0..<1)

// if you want to get a random element in an array
let greetings = ["hey", "hi", "hello", "hola"]
greetings.randomElement()

ใต้ฝากระโปรง Swift ใช้arc4random_bufเพื่อให้งานสำเร็จลุล่วง

===== Swift 4.1 / Xcode 9 =====

arc4random()ส่งคืนตัวเลขสุ่มในช่วง0ถึง4 294 967 295

drand48()ส่งคืนตัวเลขสุ่มในช่วง0.0ถึง1.0

arc4random_uniform(N)ส่งคืนตัวเลขสุ่มในช่วง0ถึงN - 1

ตัวอย่าง:

arc4random() // => UInt32 = 2739058784
arc4random() // => UInt32 = 2672503239
arc4random() // => UInt32 = 3990537167
arc4random() // => UInt32 = 2516511476
arc4random() // => UInt32 = 3959558840

drand48() // => Double = 0.88642843322303122
drand48() // => Double = 0.015582849408328769
drand48() // => Double = 0.58409022031727176
drand48() // => Double = 0.15936862653180484
drand48() // => Double = 0.38371587480719427

arc4random_uniform(3) // => UInt32 = 0
arc4random_uniform(3) // => UInt32 = 1
arc4random_uniform(3) // => UInt32 = 0
arc4random_uniform(3) // => UInt32 = 1
arc4random_uniform(3) // => UInt32 = 2

แนะนำให้ใช้arc4random_uniform ()มากกว่าโครงสร้างเช่นเดียวarc4random() % upper_boundกับที่หลีกเลี่ยง "modulo bias" เมื่อขอบเขตบนไม่ใช่กำลังสอง


Float.random()ขณะนี้มีเครื่องหมายเบต้าและให้'Float' has no member 'random'
Dale

22

คุณสามารถลองได้เช่นกัน:

let diceRoll = Int(arc4random_uniform(UInt32(6)))

ฉันต้องเพิ่ม "UInt32" เพื่อให้มันใช้งานได้


1
public func arc4random_uniform(_: UInt32) -> UInt32เมื่อฉันมองไปถึงฟังก์ชั่นนี้ผมเห็น ฉันจึงสงสัยว่าทำไมต้องแปลงพารามิเตอร์เป็นUInt32? มีอย่างอื่นเกิดขึ้นที่นี่หรือไม่?
Mark Moeykens

8

เพียงเรียกใช้ฟังก์ชันนี้และระบุช่วงต่ำสุดและสูงสุดแล้วคุณจะได้รับหมายเลขสุ่ม

eg.like randomNumber (MIN: 0, แม็กซ์: 10)และคุณจะได้รับจำนวนระหว่าง0-9

func randomNumber(MIN: Int, MAX: Int)-> Int{
    return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}

หมายเหตุ: - คุณจะได้รับผลลัพธ์เป็นจำนวนเต็มเสมอ


1
ฉันคิดว่าต้องเป็น: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

หลังจากการสอบสวนฉันเขียนสิ่งนี้:

import Foundation

struct Math {
   private static var seeded = false

   static func randomFractional() -> CGFloat {

      if !Math.seeded {
         let time = Int(NSDate().timeIntervalSinceReferenceDate)
         srand48(time)
         Math.seeded = true
      }

      return CGFloat(drand48())
   }
}

ตอนนี้คุณสามารถทำได้Math.randomFraction()เพื่อรับหมายเลขสุ่ม [0..1 [โดยไม่ต้องจำการเพาะเมล็ดก่อน หวังว่านี่จะช่วยใครสักคน: o)



3

อีกทางเลือกหนึ่งคือการใช้อัลกอริทึมxorshift128plus :

func xorshift128plus(seed0 : UInt64, _ seed1 : UInt64) -> () -> UInt64 {
    var state0 : UInt64 = seed0
    var state1 : UInt64 = seed1
    if state0 == 0 && state1 == 0 {
        state0 = 1 // both state variables cannot be 0
    }

    func rand() -> UInt64 {
        var s1 : UInt64 = state0
        let s0 : UInt64 = state1
        state0 = s0
        s1 ^= s1 << 23
        s1 ^= s1 >> 17
        s1 ^= s0
        s1 ^= s0 >> 26
        state1 = s1
        return UInt64.addWithOverflow(state0, state1).0
    }

    return rand
}

อัลกอริทึมนี้มีระยะเวลา 2 ^ 128 - 1 และผ่านการทดสอบทั้งหมดของชุดทดสอบBigCrush โปรดทราบว่าแม้ว่านี่จะเป็นเครื่องสร้างตัวเลขสุ่มหลอกคุณภาพสูงที่มีระยะเวลายาวนาน แต่ก็ไม่ใช่ตัวสร้างตัวเลขสุ่มที่ปลอดภัยด้วยการเข้ารหัสก็ไม่ได้เป็นเครื่องกำเนิดไฟฟ้าจำนวนสุ่มที่เชื่อถือได้เข้ารหัส

คุณสามารถเริ่มต้นจากเวลาปัจจุบันหรือแหล่งอื่น ๆ ของเอนโทรปีแบบสุ่ม ตัวอย่างเช่นหากคุณมีฟังก์ชันที่เรียกurand64()ว่า read a UInt64from /dev/urandomคุณสามารถใช้งานได้ดังนี้:

let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
    print(rand())
}

1
let MAX : UInt32 = 9
let MIN : UInt32 = 1 
func randomNumber()
{
   var random_number = Int(arc4random_uniform(MAX) + MIN)
   print ("random = ", random_number);    
}

ทำไมคุณไม่ให้คำอธิบายสำหรับรหัสนี้
ปฏิรูป

1

ใน Swift 3:

มันจะสร้างตัวเลขสุ่มระหว่าง 0 เพื่อ จำกัด

let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")

และถ้าฉันต้องการสร้างตัวเลขสุ่มจาก 5 ถึง 10 ไม่ใช่จาก 0 ถึง n ตัวเลข
Ritesh.mlk

1
@Rishi จาก 5 ถึง 10 จะเป็นarc4random_uniform(6) + 5
Matt Le Fleur

1

การใช้งานของฉันเป็นส่วนขยาย Int จะสร้างตัวเลขสุ่มในช่วงfrom..<to

public extension Int {
    static func random(from: Int, to: Int) -> Int {
        guard to > from else {
            assertionFailure("Can not generate negative random numbers")
            return 0
        }
        return Int(arc4random_uniform(UInt32(to - from)) + UInt32(from))
    }
}

1

นี่คือวิธีที่ฉันได้รับหมายเลขสุ่มระหว่าง 2 int!

func randomNumber(MIN: Int, MAX: Int)-> Int{
    var list : [Int] = []
    for i in MIN...MAX {
        list.append(i)
    }
    return list[Int(arc4random_uniform(UInt32(list.count)))]
}

การใช้งาน:

print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")

1

อีกทางเลือกหนึ่งคือใช้GKMersenneTwisterRandomSourceจาก GameKit เอกสารกล่าวว่า:

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

import GameKit

let minValue = 0
let maxValue = 100

var randomDistribution: GKRandomDistribution?
let randomSource = GKMersenneTwisterRandomSource()
randomDistribution = GKRandomDistribution(randomSource: randomSource, lowestValue: minValue, highestValue: maxValue)
let number = randomDistribution?.nextInt() ?? 0
print(number)

ตัวอย่างจากโค้ดตัวอย่างของ Apple: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1

ฉันสายไปปาร์ตี้🤩🎉

การใช้ฟังก์ชันที่ช่วยให้คุณเปลี่ยนขนาดของอาร์เรย์และการเลือกช่วงได้ทันทีเป็นวิธีที่หลากหลายที่สุด คุณยังสามารถใช้แผนที่เพื่อให้กระชับ ฉันใช้มันในการทดสอบประสิทธิภาพ / การทำเครื่องหมายเปรียบเทียบทั้งหมด

elementsคือจำนวนรายการในอาร์เรย์
รวมถึงตัวเลขจาก0...max

func randArr(_ elements: Int, _ max: Int) -> [Int] {
        return (0..<elements).map{ _ in Int.random(in: 0...max) }
    }

Code Sense / Placeholders มีลักษณะดังนี้ randArr(elements: Int, max: Int)

10 องค์ประกอบในอาร์เรย์ของฉันตั้งแต่ 0 ถึง 1,000

randArr(10, 1000) // [554, 8, 54, 87, 10, 33, 349, 888, 2, 77]

0

คุณสามารถใช้สิ่งนี้ในอัตราเฉพาะ:

let die = [1, 2, 3, 4, 5, 6]
 let firstRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
 let secondRoll = die[Int(arc4random_uniform(UInt32(die.count)))]

0

ให้โค้ดกับ Swift สำหรับตัวเลขสุ่มหรือสตริงสุ่ม :)

let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]

      let randomNumber = arc4random_uniform(UInt32(quotes.count))
      let quoteString = quotes[Int(randomNumber)]
      print(quoteString)

จะให้ผลลัพธ์แบบสุ่ม


0

อย่าลืมว่าตัวเลขบางตัวจะซ้ำ! ดังนั้นคุณต้องทำสิ่งที่ชอบ ....

คำถามทั้งหมดของฉันคือ 47

func getRandomNumbers(totalQuestions:Int) -> NSMutableArray
{

    var arrayOfRandomQuestions: [Int] = []

    print("arraySizeRequired = 40")
    print("totalQuestions = \(totalQuestions)")

    //This will output a 40 random numbers between 0 and totalQuestions (47)
    while arrayOfRandomQuestions.count < 40
    {

        let limit: UInt32 = UInt32(totalQuestions)

        let theRandomNumber = (Int(arc4random_uniform(limit)))

            if arrayOfRandomQuestions.contains(theRandomNumber)
            {
                print("ping")

            }
            else
            {
            //item not found
                arrayOfRandomQuestions.append(theRandomNumber)
            }

    }

    print("Random Number set = \(arrayOfRandomQuestions)")
    print("arrayOutputCount = \(arrayOfRandomQuestions.count)")


    return arrayOfRandomQuestions as! NSMutableArray

}

-2

ดูฉันมีปัญหาเดียวกัน แต่ฉันแทรกฟังก์ชันเป็นตัวแปรส่วนกลาง

เช่น

var RNumber = Int(arc4random_uniform(9)+1)

func GetCase(){

your code
}

เห็นได้ชัดว่านี่ไม่มีประสิทธิภาพดังนั้นฉันแค่คัดลอกและวางโค้ดลงในฟังก์ชันเพื่อให้สามารถใช้ซ้ำได้จากนั้น xcode แนะนำให้ฉันตั้งค่า var เป็นค่าคงที่เพื่อให้รหัสของฉันเป็น

func GetCase() {

let RNumber = Int(arc4random_uniform(9)+1)

   if categoria == 1 {
    }
}

นั่นเป็นส่วนหนึ่งของรหัสของฉันดังนั้น xcode จึงบอกบางสิ่งที่ไม่สามารถเปลี่ยนแปลงได้และการเริ่มต้น แต่มันก็สร้างแอปอยู่ดีและคำแนะนำนั้นก็หายไป

หวังว่ามันจะช่วยได้

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