Générer des nombres aléatoires avec Swift
J'ai besoin de générer un nombre aléatoire.
Il semble que la fonction arc4random
n'existe plus ainsi que la fonction arc4random_uniform
.
Les options que j'ai sont arc4random_stir()
, arc4random_buf(UnsafeMutablePointer<Void>, Int)
, et arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32)
.
Je ne trouve aucun document sur les fonctions et aucun commentaire dans les fichiers d'en-tête ne donne d'indices.
15 réponses
===== 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 4.1 / Xcode 9 =====
arc4random()
renvoie un nombre aléatoire dans l'intervalle de 0 pour 4 294 967 295
drand48()
renvoie un nombre aléatoire dans l'intervalle de 0.0 pour 1.0
arc4random_uniform(N)
renvoie un nombre aléatoire dans l'intervalle de 0 de N - 1
Exemples:
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 () {[8] } est recommandé sur des constructions comme arc4random() % upper_bound
car il évite le "biais modulo" lorsque la limite supérieure n'est pas une puissance de deux.
Vous pouvez aussi essayer:
let diceRoll = Int(arc4random_uniform(UInt32(6)))
J'ai dû ajouter "UInt32" pour le faire fonctionner.
Il suffit d'appeler cette fonction et de fournir une portée minimale et maximale du nombre et vous obtiendrez un nombre aléatoire.
Par exemple.comme randomNumber(MIN: 0, MAX: 10) et vous obtiendrez le nombre entre 0 à 9.
func randomNumber(MIN: Int, MAX: Int)-> Int{
return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}
Note: - vous obtiendrez toujours un nombre entier.
Après une enquête, j'ai écrit ceci:
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())
}
}
Maintenant, vous pouvez simplement faire Math.randomFraction()
pour obtenir des nombres aléatoires [0..1 [sans avoir à se souvenir de l'ensemencement en premier. J'espère que cela aide quelqu'un: o)
Une autre option consiste à utiliser l'algorithme 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
}
Cet algorithme a une période de 2^128-1 et passe tous les tests de la suite de testsBigCrush . Notez que s'il s'agit d'un générateur de nombres pseudo-aléatoires de haute qualité avec une longue période, ce n'est pas un générateur de nombres aléatoires cryptographiquement sécurisé.
Vous pouvez le semer à partir de l'heure actuelle ou de toute autre source aléatoire d'entropie. Par exemple, si vous avez eu une fonction appelé urand64()
qui lit un UInt64
de /dev/urandom
, Vous pouvez l'utiliser comme ceci:
let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
print(rand())
}
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}
Dans Swift 3:
Il va générer un nombre aléatoire entre 0 pour limiter
let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")
Mon implémentation en tant qu'extension Int. Va générer des nombres aléatoires dans la plage 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))
}
}
Mise à Jour avec swift 4.2 :
let randomInt = Int.random(in: 1..<5)
let randomFloat = Float.random(in: 1..<10)
let randomDouble = Double.random(in: 1...100)
let randomCGFloat = CGFloat.random(in: 1...1000)
Vous pouvez l'utiliser dans le taux spécifique:
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)))]
Permet de coder avec Swift pour le nombre aléatoire ou la chaîne aléatoire:)
let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]
let randomNumber = arc4random_uniform(UInt32(quotes.count))
let quoteString = quotes[Int(randomNumber)]
print(quoteString)
Il vous donnera la sortie au hasard.
N'oubliez pas que certains chiffres vont se répéter! donc, vous devez faire quelque chose comme....
Mon totalQuestions était 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
}
C'est ainsi que j'obtiens un nombre aléatoire entre 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)))]
}
Utilisation:
print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")
Une autre option consiste à utiliser GKMersenneTwisterRandomSource de GameKit. Les docs disent:
Une source pseudo-aléatoire déterministe qui génère des nombres aléatoires basé sur un algorithme de Mersenne twister. C'est un aléatoire déterministe source appropriée pour créer des mécanismes de jeu fiables. Il est légèrement plus lent qu'une source Arc4, mais plus aléatoire, en ce sens qu'il a un plus longue période jusqu'à la répétition des séquences. Bien que déterministe, c'est pas un hasard cryptographique source. Il est cependant adapté pour obscurcissement des données de jeu.
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)
Exemple tiré de L'exemple de code D'Apple: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift
Regardez, j'ai eu le MÊME PROBLÈME MAIS j'insère la fonction en tant que variable globale
Comme
var RNumber = Int(arc4random_uniform(9)+1)
func GetCase(){
your code
}
Évidemment, ce N'est pas efficace, alors je viens de copier et coller le code dans la fonction pour qu'il puisse être réutilisable, alors xcode me suggère de définir la var comme constante pour que mon code soit
func GetCase() {
let RNumber = Int(arc4random_uniform(9)+1)
if categoria == 1 {
}
}
Eh bien, c'est une partie de mon code, donc xcode me dit quelque chose d'inmutable et d'initialisation mais, il construit l'application de toute façon et ce conseil disparaît simplement
J'espère que ça aide