541 Stimmen

Wie generiere ich eine Zufallszahl in Swift?

Ich stelle fest, dass das Swift-Buch eine Implementierung eines Zufallszahlengenerators bereitgestellt hat. Ist es bewährte Praxis, diese Implementierung zu kopieren und einzufügen? Oder gibt es eine Bibliothek, die wir jetzt verwenden können?

674voto

Catfish_Man Punkte 40261

Swift 4.2+

Swift 4.2, das mit Xcode 10 ausgeliefert wurde, bietet neue, benutzerfreundliche Zufallsfunktionen für viele Datentypen.

Sie rufen einfach die Methode random() für numerische Typen auf.

let randomInt = Int.random(in: 0..<6)
let randomDouble = Double.random(in: 2.71828...3.14159)
let randomBool = Bool.random()

500voto

John Pavley Punkte 5316

Verwenden Sie arc4random_uniform(n) für eine zufällige Ganzzahl zwischen 0 und n-1.

let diceRoll = Int(arc4random_uniform(6) + 1)

Gießen Sie das Ergebnis in Int, damit Sie Ihre Variablen nicht explizit als UInt32 typen müssen (was nicht sehr Swift-y wirkt).

116voto

jstn Punkte 2326

Bearbeiten: Aktualisiert für Swift 3.0

arc4random funktioniert gut in Swift, aber die Basisfunktionen sind auf 32-Bit-Ganzzahltypen begrenzt (Int ist auf dem iPhone 5S und modernen Macs 64-Bit). Hier ist eine generische Funktion für eine Zufallszahl eines Typs, der durch ein ganzzahliges Literal ausdrückbar ist:

public func arc4random(_ type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, MemoryLayout.size)
    return r
}

Wir können diese neue generische Funktion verwenden, um UInt64 zu erweitern, indem wir Grenzargumente hinzufügen und den Modulobias mildern. (Das wurde direkt aus arc4random.c übernommen)

public extension UInt64 {
    public static func random(lower: UInt64 = min, upper: UInt64 = max) -> UInt64 {
        var m: UInt64
        let u = upper - lower
        var r = arc4random(UInt64.self)

        if u > UInt64(Int64.max) {
            m = 1 + ~u
        } else {
            m = ((max - (u * 2)) + 1) % u
        }

        while r < m {
            r = arc4random(UInt64.self)
        }

        return (r % u) + lower
    }
}

Damit können wir auch Int64 für dieselben Argumente erweitern und mit Überlauf umgehen:

public extension Int64 {
    public static func random(lower: Int64 = min, upper: Int64 = max) -> Int64 {
        let (s, overflow) = Int64.subtractWithOverflow(upper, lower)
        let u = overflow ? UInt64.max - UInt64(~s) : UInt64(s)
        let r = UInt64.random(upper: u)

        if r > UInt64(Int64.max)  {
            return Int64(r - (UInt64(~lower) + 1))
        } else {
            return Int64(r) + lower
        }
    }
}

Um die Familie zu vervollständigen...

private let _wordSize = __WORDSIZE

public extension UInt32 {
    public static func random(lower: UInt32 = min, upper: UInt32 = max) -> UInt32 {
        return arc4random_uniform(upper - lower) + lower
    }
}

public extension Int32 {
    public static func random(lower: Int32 = min, upper: Int32 = max) -> Int32 {
        let r = arc4random_uniform(UInt32(Int64(upper) - Int64(lower)))
        return Int32(Int64(r) + Int64(lower))
    }
}

public extension UInt {
    public static func random(lower: UInt = min, upper: UInt = max) -> UInt {
        switch (_wordSize) {
            case 32: return UInt(UInt32.random(UInt32(lower), upper: UInt32(upper)))
            case 64: return UInt(UInt64.random(UInt64(lower), upper: UInt64(upper)))
            default: return lower
        }
    }
}

public extension Int {
    public static func random(lower: Int = min, upper: Int = max) -> Int {
        switch (_wordSize) {
            case 32: return Int(Int32.random(Int32(lower), upper: Int32(upper)))
            case 64: return Int(Int64.random(Int64(lower), upper: Int64(upper)))
            default: return lower
        }
    }
}

Nach all dem können wir endlich etwas wie das hier tun:

let würfelwurf = UInt64.random(lower: 1, upper: 7)

95voto

Groot Punkte 13172

Bearbeiten für Swift 4.2

Ab Swift 4.2 kannst du anstelle der importierten C-Funktion arc4random_uniform() jetzt auch die eigenen nativen Funktionen von Swift verwenden.

// Generiert Ganzzahlen von 0 bis einschließlich 10
Int.random(in: 0 ... 10)

Du kannst random(in:) auch für andere primitive Werte verwenden, wie zum Beispiel Int, Double, Float und sogar Bool.

Swift-Versionen < 4.2

Mit dieser Methode wird ein zufälliger Int-Wert zwischen dem angegebenen Minimum und Maximum generiert.

func randomInt(min: Int, max: Int) -> Int {
    return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}

59voto

fockus Punkte 730

Ich habe diesen Code verwendet:

var k: Int = random() % 10;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X