Je me rends compte que le livre Swift a fourni une implémentation d'un générateur de nombres aléatoires. La meilleure pratique est-elle de copier et coller cette implémentation dans son propre programme? Ou existe-t-il une bibliothèque que nous pouvons utiliser maintenant?
443
À utiliser
arc4random_uniform(n)
pour un entier aléatoire compris entre 0 et n-1.Castez le résultat sur Int pour ne pas avoir à taper explicitement vos vars en tant que
UInt32
(ce qui semble non Swifty).la source
0
. Dans votre code,diceRoll
pourrait l'être0
. Je dis juste ...Int(arc4random_uniform(6)+1)
.arc3random_uniform(n)
aUInt32(n)
si vous utilisez une valeur qui n'est pas déjà de ce type.Edit: mis à jour pour Swift 3.0
arc4random
fonctionne bien dans Swift, mais les fonctions de base sont limitées aux types entiers 32 bits (Int
64 bits sur iPhone 5S et Mac modernes). Voici une fonction générique pour un nombre aléatoire d'un type exprimable par un littéral entier:Nous pouvons utiliser cette nouvelle fonction générique pour étendre
UInt64
, ajouter des arguments aux limites et atténuer le biais modulo. (Ceci est levé directement depuis arc4random.c )Avec cela, nous pouvons étendre
Int64
pour les mêmes arguments, traitant du débordement:Pour compléter la famille ...
Après tout cela, nous pouvons enfin faire quelque chose comme ça:
la source
var r = arc4random(UInt64)
. Veuillez conseiller ce que vous vouliez dire ici?arc4random
(définie dans le premier bloc de code) avec l'argumentUInt64
qui est aType
.arc4random_buf
. Le but de ces extensions est de faire exactement ce quearc4random_uniform
fait (atténuer le biais modulo) sauf pour les types 64 bits.Modifier pour Swift 4.2
À partir de Swift 4.2, au lieu d'utiliser la fonction C importée arc4random_uniform (), vous pouvez désormais utiliser les propres fonctions natives de Swift.
Vous pouvez également utiliser
random(in:)
pour obtenir des valeurs aléatoires pour d'autres valeurs primitives; tels que Int, Double, Float et même Bool.Versions Swift <4.2
Cette méthode générera une
Int
valeur aléatoire entre le minimum et le maximum donnésla source
J'ai utilisé ce code:
la source
random is unavailable in Swift: Use arc4random instead.
Depuis iOS 9, vous pouvez utiliser les nouvelles classes GameplayKit pour générer des nombres aléatoires de différentes manières.
Vous avez le choix entre quatre types de sources: une source aléatoire générale (sans nom, jusqu'au système pour choisir ce qu'il fait), congruentielle linéaire, ARC4 et Mersenne Twister. Ceux-ci peuvent générer des ints, des flottants et des bools aléatoires.
Au niveau le plus simple, vous pouvez générer un nombre aléatoire à partir de la source aléatoire intégrée du système comme ceci:
Cela génère un nombre compris entre -2 147 483 648 et 2 147 483 647. Si vous voulez un nombre entre 0 et une limite supérieure (exclusive), vous utiliseriez ceci:
GameplayKit a des constructeurs de commodité intégrés pour fonctionner avec les dés. Par exemple, vous pouvez lancer un dé à six faces comme ceci:
De plus, vous pouvez façonner la distribution aléatoire en utilisant des choses comme GKShuffledDistribution. Cela prend un peu plus d'explication, mais si vous êtes intéressé, vous pouvez lire mon tutoriel sur les nombres aléatoires GameplayKit .
la source
import GameplayKit
. Swift 3 a changé la syntaxe enGKRandomSource.sharedRandom().nextInt(upperBound: 6)
Vous pouvez le faire de la même manière que vous le feriez en C:
randomNumber
est supposé être de typeUInt32
(un entier non signé 32 bits)la source
rand
,arc4random
,drand48
et amis sont tous dans leDarwin
module. Il est déjà importé pour vous si vous créez une application Cocoa, UIKit ou Foundation, mais vous en aurez besoinimport Darwin
dans les aires de jeux.Utilisation
arc4random_uniform()
Usage:
arc4random_uniform(someNumber: UInt32) -> UInt32
Cela vous donne des entiers aléatoires dans la plage
0
desomeNumber - 1
.La valeur maximale pour
UInt32
est de 4 294 967 295 (c'est-à-dire2^32 - 1
).Exemples:
Tirage au sort
Lancer de dés
Jour aléatoire en octobre
Année aléatoire dans les années 1990
Forme générale:
où
number
,max
etmin
sontUInt32
.Qu'en est-il de...
arc4random ()
Vous pouvez également obtenir un nombre aléatoire en utilisant
arc4random()
, ce qui produitUInt32
entre 0 et 2 ^ 32-1. Ainsi, pour obtenir un nombre aléatoire entre0
etx-1
, vous pouvez le diviser parx
et prendre le reste. Ou en d'autres termes, utilisez l' opérateur restant (%) :Cependant, cela produit un léger biais modulo (voir aussi ici et ici ), c'est pourquoi
arc4random_uniform()
est recommandé.Conversion vers et depuis
Int
Normalement, ce serait bien de faire quelque chose comme ça afin de faire des allers-retours entre
Int
etUInt32
:Le problème, cependant, est qu'il
Int
a une gamme de-2,147,483,648...2,147,483,647
systèmes 32 bits et une gamme de-9,223,372,036,854,775,808...9,223,372,036,854,775,807
systèmes 64 bits. Comparez cela à laUInt32
gamme de0...4,294,967,295
. LeU
deUInt32
signifie non signé .Considérez les erreurs suivantes:
Il vous suffit donc de vous assurer que vos paramètres d'entrée se situent dans la
UInt32
plage et que vous n'avez pas besoin non plus d'une sortie en dehors de cette plage.la source
Exemple pour un nombre aléatoire entre 10 (0-9);
Code très facile - simple et court.
la source
J'ai pu simplement utiliser
rand()
pour obtenir un CInt aléatoire. Vous pouvez en faire un Int en utilisant quelque chose comme ceci:Vous pouvez utiliser votre fonction aléatoire C préférée et simplement la convertir en valeur en Int si nécessaire.
la source
random()
, qui renvoie unInt
plutôt queUInt32
- et comme @SomeGuy l'a mentionné, appelez simplementsrandom(arc4random())
une fois n'importe où avant de l'utiliser pour vous assurer qu'il a une graine aléatoire différente pour chaque exécution de votre programme.La réponse de @ jstn est bonne, mais un peu bavarde. Swift est connu comme un langage orienté protocole, nous pouvons donc obtenir le même résultat sans avoir à implémenter du code passe-partout pour chaque classe de la famille d'entiers, en ajoutant une implémentation par défaut pour l'extension de protocole.
Maintenant, nous pouvons faire:
et toutes les autres classes entières sont correctes.
la source
Dans Swift 4.2, vous pouvez générer des nombres aléatoires en appelant la
random()
méthode sur le type numérique que vous souhaitez, en fournissant la plage avec laquelle vous souhaitez travailler. Par exemple, cela génère un nombre aléatoire compris entre 1 et 9, inclus des deux côtésAussi avec d'autres types
la source
Voici une bibliothèque qui fait bien le travail https://github.com/thellimist/SwiftRandom
la source
la source
Je voudrais ajouter aux réponses existantes que l'exemple du générateur de nombres aléatoires dans le livre Swift est un générateur de congruence linéaire (LCG), il est très limité et ne devrait pas être sauf pour les exemples triviaux incontournables, où la qualité de l'aléatoire ne fait pas importe pas du tout. Et un LCG ne doit jamais être utilisé à des fins cryptographiques .
arc4random()
est bien meilleur et peut être utilisé dans la plupart des cas, mais ne doit pas être utilisé à des fins cryptographiques.Si vous voulez quelque chose qui est garanti cryptographiquement sécurisé, utilisez
SecCopyRandomBytes()
. Notez que si vous construisez un générateur de nombres aléatoires dans quelque chose, quelqu'un d'autre pourrait finir par (mal) l'utiliser à des fins cryptographiques (comme la génération de mot de passe, de clé ou de sel), alors vous devriez envisager d'utiliser deSecCopyRandomBytes()
toute façon, même si votre besoin ne le fait pas '' t tout à fait exiger cela.la source
Depuis Swift 4.2
Il existe un nouvel ensemble d'API:
Tous les types numériques ont désormais la
random(in:)
méthode qui prendrange
.Il renvoie un nombre uniformément réparti dans cette plage.
TL; DR
Eh bien, qu'est-ce qui ne va pas avec la "bonne" vieille façon?
Vous devez utiliser des API C importées (elles sont différentes entre les plates-formes) .
Et de plus...
Si vous utilisez
arc4random()
(pour calculer le reste) commearc4random() % aNumber
, le résultat n'est pas uniformément réparti entre le0
etaNumber
. Il existe un problème appelé biais Modulo .Biais modulo
Normalement, la fonction génère un nombre aléatoire entre
0
et MAX (dépend du type, etc.) . Pour faire un exemple rapide et facile, disons que le nombre maximum est7
et que vous vous souciez d'un nombre aléatoire dans la plage0 ..< 2
(ou l'intervalle [0, 3) si vous préférez) .Les probabilités pour les nombres individuels sont:
En d'autres termes, vous êtes plus susceptible de vous retrouver avec 0 ou 1 que 2 . Bien sûr, sachant que cela est extrêmement simplifié et que le nombre MAX est beaucoup plus élevé, ce qui le rend plus "équitable".
la source
Sans arc4Random_uniform () dans certaines versions de Xcode (en 7.1, il s'exécute mais ne se remplit pas automatiquement pour moi). Vous pouvez le faire à la place.
Pour générer un nombre aléatoire de 0 à 5. Première
alors
la source
Ici, 5 s'assurera que le nombre aléatoire est généré de zéro à quatre. Vous pouvez définir la valeur en conséquence.
la source
Swift 4.2
Au revoir pour importer Foundation C lib
arc4random_uniform()
Plus @ officiel
la source
Le code suivant produira un nombre aléatoire sécurisé compris entre 0 et 255:
Vous l'appelez comme ceci:
Pour les plus grands nombres, cela devient plus compliqué.
C'est le mieux que j'ai pu trouver:
Ces méthodes utilisent un nombre aléatoire supplémentaire pour déterminer combien de
UInt8
s vont être utilisés pour créer le nombre aléatoire. La dernière ligne convertit le[UInt8]
enUInt16
ouUInt32
.Je ne sais pas si les deux derniers comptent toujours comme vraiment aléatoires, mais vous pouvez le modifier à votre guise :)
la source
Swift 4.2
Swift 4.2 a inclus une API de nombres aléatoires native et assez complète dans la bibliothèque standard. ( Proposition Swift Evolution SE-0202 )
Tous les types de nombres ont un aléatoire statique (in :) qui prend la plage et renvoie le nombre aléatoire dans la plage donnée
la source
Pour iOS, macOS et tvOS, vous pouvez utiliser une source aléatoire à l'échelle du système dans le cadre de Xcode
GameKit
. Ici vous pouvez trouver laGKRandomSource
classe avec sasharedRandom()
méthode de classe:Ou utilisez simplement une
randomElement()
méthode qui renvoie un élément aléatoire de la collection:la source
Vous pouvez utiliser
GeneratorOf
comme ceci:la source
J'utilise ce code pour générer un nombre aléatoire:
la source
Détails
xCode 9.1, Swift 4
Solution orientée mathématique (1)
Utilisation de la solution (1)
Solution orientée programmeurs (2)
Utilisation de la solution (2)
Échantillon complet
Exemple de résultat
la source