Mir ist klar, dass das Swift-Buch eine Implementierung eines Zufallszahlengenerators enthielt. Ist es die beste Vorgehensweise, diese Implementierung zu kopieren und in das eigene Programm einzufügen? Oder gibt es eine Bibliothek, die dies jetzt tun kann?
443
Verwenden Sie
arc4random_uniform(n)
für eine zufällige Ganzzahl zwischen 0 und n-1.Wandeln Sie das Ergebnis in Int um, damit Sie Ihre Vars nicht explizit als eingeben müssen
UInt32
(was nicht schnell zu sein scheint).quelle
0
. In Ihrem CodediceRoll
könnte sein0
. Ich sage nur ...Int(arc4random_uniform(6)+1)
.arc3random_uniform(n)
,UInt32(n)
wenn Sie einen Wert verwenden, der noch nicht von diesem Typ ist.Bearbeiten: Aktualisiert für Swift 3.0
arc4random
funktioniert gut in Swift, aber die Basisfunktionen sind auf 32-Bit-Integer-Typen beschränkt (Int
64-Bit auf iPhone 5S und modernen Macs). Hier ist eine generische Funktion für eine Zufallszahl eines Typs, der durch ein ganzzahliges Literal ausgedrückt werden kann:Wir können diese neue generische Funktion verwenden, um zu erweitern
UInt64
, Grenzargumente hinzuzufügen und die Modulo-Verzerrung zu verringern. (Dies wird direkt von arc4random.c angehoben. )Damit können wir
Int64
für die gleichen Argumente, die sich mit Überlauf befassen, erweitern:Um die Familie zu vervollständigen ...
Nach all dem können wir endlich so etwas machen:
quelle
var r = arc4random(UInt64)
. Bitte raten Sie, was Sie hier gemeint haben.arc4random
(definiert im ersten Codeblock) mit dem Argument aufzurufen,UInt64
das a istType
.arc4random_buf
. Der Zweck dieser Erweiterungen besteht darin, genau das zu tunarc4random_uniform
(Modulo Bias zu verringern), mit Ausnahme von 64-Bit-Typen.Bearbeiten für Swift 4.2
Ab Swift 4.2 können Sie anstelle der importierten C-Funktion arc4random_uniform () jetzt die eigenen nativen Funktionen von Swift verwenden.
Sie können auch
random(in:)
Zufallswerte für andere primitive Werte abrufen. wie Int, Double, Float und sogar Bool.Schnelle Versionen <4.2
Diese Methode generiert einen zufälligen
Int
Wert zwischen dem angegebenen Minimum und Maximumquelle
Ich habe diesen Code verwendet:
quelle
random is unavailable in Swift: Use arc4random instead.
Ab iOS 9 können Sie die neuen GameplayKit-Klassen verwenden, um Zufallszahlen auf verschiedene Arten zu generieren.
Sie haben vier Quelltypen zur Auswahl: eine allgemeine Zufallsquelle (unbenannt, bis auf das System, um auszuwählen, was sie tut), linear kongruent, ARC4 und Mersenne Twister. Diese können zufällige Ints, Floats und Bools erzeugen.
Auf der einfachsten Ebene können Sie eine Zufallszahl aus der integrierten Zufallsquelle des Systems wie folgt generieren:
Das ergibt eine Zahl zwischen -2.147.483.648 und 2.147.483.647. Wenn Sie eine Zahl zwischen 0 und einer Obergrenze (exklusiv) möchten, verwenden Sie Folgendes:
GameplayKit verfügt über einige praktische Konstruktoren, die für die Arbeit mit Würfeln integriert sind. Zum Beispiel können Sie einen sechsseitigen Würfel wie folgt würfeln:
Außerdem können Sie die Zufallsverteilung mithilfe von GKShuffledDistribution gestalten. Das braucht etwas mehr Erklärung, aber wenn Sie interessiert sind, können Sie mein Tutorial über GameplayKit-Zufallszahlen lesen .
quelle
import GameplayKit
. Swift 3 änderte die Syntax zuGKRandomSource.sharedRandom().nextInt(upperBound: 6)
Sie können es genauso machen wie in C:
randomNumber
Es wird davon ausgegangen, dass es sich um einen Typ handeltUInt32
(eine vorzeichenlose 32-Bit-Ganzzahl).quelle
rand
,arc4random
,drand48
und Freunde sind alle in demDarwin
Modul. Es ist bereits für Sie importiert, wenn Sie eine Kakao-, UIKit- oder Foundation-App erstellen, aber Sie müssen esimport Darwin
auf Spielplätzen tun .Verwenden
arc4random_uniform()
Verwendungszweck:
arc4random_uniform(someNumber: UInt32) -> UInt32
Dies gibt Ihnen zufällige ganze Zahlen im Bereich
0
bissomeNumber - 1
.Der Maximalwert für
UInt32
beträgt 4.294.967.295 (dh2^32 - 1
).Beispiele:
Münzwurf
Würfelwurf
Zufälliger Tag im Oktober
Zufälliges Jahr in den 1990er Jahren
Generelle Form:
wo
number
,max
undmin
sindUInt32
.Wie wäre es mit...
arc4random ()
Sie können auch eine Zufallszahl erhalten, indem Sie
arc4random()
eineUInt32
zwischen 0 und 2 ^ 32-1 erzeugen . Um eine Zufallszahl zwischen0
und zu erhaltenx-1
, können Sie sie durch dividierenx
und den Rest nehmen. Oder verwenden Sie mit anderen Worten den Restoperator (%) :Dies erzeugt jedoch eine leichte Modulo-Vorspannung (siehe auch hier und hier ), weshalb
arc4random_uniform()
empfohlen wird.Konvertieren von und nach
Int
Normalerweise wäre es in Ordnung, so etwas zu tun, um zwischen
Int
und hin und her zu konvertierenUInt32
:Das Problem ist jedoch, dass
Int
es eine Reichweite von-2,147,483,648...2,147,483,647
32-Bit-Systemen und eine Reichweite von-9,223,372,036,854,775,808...9,223,372,036,854,775,807
64-Bit-Systemen gibt. Vergleichen Sie dies mit demUInt32
Bereich von0...4,294,967,295
. DasU
vonUInt32
bedeutet unsigniert .Beachten Sie die folgenden Fehler:
Sie müssen also nur sicherstellen, dass Ihre Eingabeparameter innerhalb des
UInt32
Bereichs liegen und dass Sie auch keine Ausgabe benötigen, die außerhalb dieses Bereichs liegt.quelle
Beispiel für eine Zufallszahl zwischen 10 (0-9);
Sehr einfacher Code - einfach und kurz.
quelle
Ich konnte nur verwenden
rand()
, um ein zufälliges CInt zu erhalten. Sie können daraus ein Int machen, indem Sie Folgendes verwenden:Sie können Ihre bevorzugte C-Zufallsfunktion verwenden und bei Bedarf einfach in den Wert in Int konvertieren.
quelle
random()
, was einInt
eher als zurückgibtUInt32
- und wie @SomeGuy erwähnt, einfachsrandom(arc4random())
einmal irgendwo aufrufen , bevor Sie es verwenden, um sicherzustellen, dass es für jede Ausführung Ihres Programms einen anderen, zufälligen Startwert hat.@ jstns Antwort ist gut, aber etwas ausführlich. Swift ist als protokollorientierte Sprache bekannt, sodass wir das gleiche Ergebnis erzielen können, ohne für jede Klasse in der Integer-Familie Boilerplate-Code implementieren zu müssen, indem wir eine Standardimplementierung für die Protokollerweiterung hinzufügen.
Jetzt können wir tun:
und alle anderen ganzzahligen Klassen sind in Ordnung.
quelle
In Swift 4.2 können Sie Zufallszahlen generieren, indem Sie die
random()
Methode für einen beliebigen numerischen Typ aufrufen und den Bereich angeben, mit dem Sie arbeiten möchten. Dies erzeugt beispielsweise eine Zufallszahl im Bereich von 1 bis 9, einschließlich auf beiden SeitenAuch bei anderen Typen
quelle
Hier ist eine Bibliothek, die ihre Arbeit gut macht https://github.com/thellimist/SwiftRandom
quelle
quelle
Ich möchte zu den vorhandenen Antworten hinzufügen, dass das Beispiel des Zufallszahlengenerators im Swift-Buch ein linearer Kongruenzgenerator (Linear Congruence Generator, LCG) ist. Es ist stark eingeschränkt und sollte nur die trivialen Beispiele sein, bei denen die Qualität der Zufälligkeit dies nicht tut ist überhaupt nicht wichtig. Und ein LCG sollte niemals für kryptografische Zwecke verwendet werden .
arc4random()
ist viel besser und kann für die meisten Zwecke verwendet werden, sollte aber auch hier nicht für kryptografische Zwecke verwendet werden.Wenn Sie etwas wünschen, das garantiert kryptografisch sicher ist, verwenden Sie
SecCopyRandomBytes()
. Beachten Sie, dass, wenn Sie einen Zufallszahlengenerator in etwas einbauen, jemand anderes ihn möglicherweise (falsch) für kryptografische Zwecke (wie Kennwort-, Schlüssel- oder Salzgenerierung) verwendet. Sie sollten die VerwendungSecCopyRandomBytes()
trotzdem in Betracht ziehen , auch wenn dies nicht erforderlich ist. Ich brauche das nicht ganz.quelle
Seit Swift 4.2
Es gibt eine neue Reihe von APIs:
Alle numerischen Typen haben jetzt die
random(in:)
Methode, die akzeptiert wirdrange
.Es wird eine gleichmäßig in diesem Bereich verteilte Zahl zurückgegeben.
TL; DR
Nun, was ist los mit dem "guten" alten Weg?
Sie müssen importierte C- APIs verwenden (diese unterscheiden sich zwischen den Plattformen) .
Und außerdem ...
Wenn Sie
arc4random()
(um den Rest zu berechnen) wie verwendenarc4random() % aNumber
, wird das Ergebnis nicht gleichmäßig zwischen0
und verteiltaNumber
. Es gibt ein Problem, das als Modulo-Bias bezeichnet wird .Modulo Bias
Normalerweise generiert die Funktion eine Zufallszahl zwischen
0
und MAX (abhängig vom Typ usw.) . Um ein schnelles und einfaches Beispiel zu erstellen, nehmen wir an, die maximale Anzahl ist7
und Sie interessieren sich für eine Zufallszahl im Bereich0 ..< 2
(oder im Intervall [0, 3), wenn Sie dies bevorzugen) .Die Wahrscheinlichkeiten für einzelne Zahlen sind:
Mit anderen Worten : Sie sind eher am Ende mit 0 oder 1 als 2 . Bedenken Sie natürlich, dass dies extrem vereinfacht ist und die MAX- Zahl viel höher ist, was es "fairer" macht.
quelle
Ohne arc4Random_uniform () in einigen Versionen von Xcode (in 7.1 wird es ausgeführt, aber für mich nicht automatisch vervollständigt). Sie können dies stattdessen tun.
So generieren Sie eine Zufallszahl von 0-5. Zuerst
Dann
quelle
Hier wird 5 sicherstellen, dass die Zufallszahl durch null bis vier erzeugt wird. Sie können den Wert entsprechend einstellen.
quelle
Swift 4.2
Tschüss, um Foundation C lib zu importieren
arc4random_uniform()
Mehr @ Offiziell
quelle
Der folgende Code erzeugt eine sichere Zufallszahl zwischen 0 und 255:
Sie nennen es so:
Bei größeren Zahlen wird es komplizierter.
Dies ist das Beste, was ich mir vorstellen kann:
Diese Methoden verwenden eine zusätzliche Zufallszahl, um zu bestimmen, wie viele
UInt8
s zum Erstellen der Zufallszahl verwendet werden sollen. Die letzte Zeile konvertiert das[UInt8]
nachUInt16
oderUInt32
.Ich weiß nicht, ob die letzten beiden immer noch als wirklich zufällig gelten, aber Sie können es nach Ihren Wünschen anpassen :)
quelle
Swift 4.2
Swift 4.2 hat eine native und ziemlich voll funktionsfähige Zufallszahlen-API in die Standardbibliothek aufgenommen. ( Swift Evolution Vorschlag SE-0202 )
Alle Zahlentypen haben den statischen Zufall (in :), der den Bereich übernimmt und die Zufallszahl im angegebenen Bereich zurückgibt
quelle
Für iOS, macOS und tvOS können Sie im Xcode-Framework systemweite Zufallsquellen verwenden
GameKit
. Hier finden Sie dieGKRandomSource
Klasse mit ihrersharedRandom()
Klassenmethode:Oder verwenden Sie einfach eine
randomElement()
Methode, die ein zufälliges Element der Sammlung zurückgibt:quelle
Sie können
GeneratorOf
wie folgt verwenden:quelle
Ich benutze diesen Code, um eine Zufallszahl zu generieren:
quelle
Einzelheiten
xCode 9.1, Swift 4
Mathematikorientierte Lösung (1)
Verwendung der Lösung (1)
Programmiererorientierte Lösung (2)
Verwendung der Lösung (2)
Vollständige Probe
Beispielergebnis
quelle