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?
Antworten
Zu viele Anzeigen?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()
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)
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)))
}
- See previous answers
- Weitere Antworten anzeigen