web-dev-qa-db-fra.com

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 aussi bien 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 aucune documentation sur les fonctions et aucun commentaire dans les fichiers d'en-tête ne donne d'indices.

87
Big_Mac

===== 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()

Sous le capot, Swift utilise arc4random_buf pour exécuter son travail.

===== Swift 4.1/Xcode 9 =====

arc4random() renvoie un nombre aléatoire compris entre et 4 294 967 295

drand48() renvoie un nombre aléatoire compris entre . et 1.

arc4random_uniform(N) renvoie un nombre aléatoire compris entre et 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 () est recommandé sur les constructions telles que arc4random() % upper_bound, car il évite le "biais modulo" lorsque la borne supérieure n'est pas une puissance de deux.

221
Arsen

Vous pouvez aussi essayer:

let diceRoll = Int(arc4random_uniform(UInt32(6)))

J'ai dû ajouter "UInt32" pour que cela fonctionne.

22
Fernando Cardenas

Appelez simplement cette fonction et indiquez une plage de nombres minimum et maximum et vous obtiendrez un nombre aléatoire.

eg.like randomNumber (MIN: 0, MAX: 10) et vous obtiendrez un nombre compris entre à 9.

func randomNumber(MIN: Int, MAX: Int)-> Int{
    return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}

Remarque: - Vous obtiendrez toujours un nombre entier.

8
PRAVEEN

Après 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 utiliser Math.randomFraction() pour obtenir des nombres aléatoires [0..1 [sans avoir à vous souvenir de l'ensemencement préalable. J'espère que cela aide quelqu'un: o)

5
Melodius

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)
3
Quentin N

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 tests BigCrush . Notez que s'il s'agit d'un générateur de nombres pseudo-aléatoires de haute qualité avec une longue période, , il ne s'agit pas d'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 d'entropie aléatoire. Par exemple, si vous avez une fonction appelée urand64() qui lit un UInt64 à partir de /dev/urandom, vous pouvez l'utiliser comme suit:

let Rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
    print(Rand())
}
3
David Conrad

C'est comme ça 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)))]
}

usage:

print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")
1
Ilan Sagital

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))")
1
Mili Shah
let MAX : UInt32 = 9
let MIN : UInt32 = 1 
func randomNumber()
{
   var random_number = Int(arc4random_uniform(MAX) + MIN)
   print ("random = ", random_number);    
}
1
Rajesh Sharma

Mon implémentation en tant qu'extension Int. Générera 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))
    }
}
1
anatoliy_v

Je suis en retard à la fête ????????

Utiliser une fonction qui vous permet de changer la taille du tableau et la sélection de plage à la volée est la méthode la plus polyvalente. Vous pouvez également utiliser la carte, donc c'est très concis. Je l'utilise dans tous mes tests de performance/marquage au banc.

elements est le nombre d'éléments dans le tableau
comprenant uniquement les numéros de 0...max

func randArr(_ elements: Int, _ max: Int) -> [Int] {
        return (0..<elements).map{ _ in Int.random(in: 0...max) }
    }

Code Sense/Placeholders ressemble à ceci. randArr(elements: Int, max: Int)

10 éléments dans mon tableau allant de 0 à 1000.

randArr(10, 1000) // [554, 8, 54, 87, 10, 33, 349, 888, 2, 77]
0
tymac

Permet de coder avec Swift pour le nombre 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)

cela vous donnera une sortie au hasard.

0

Une autre option consiste à utiliser GKMersenneTwisterRandomSource à partir de GameKit. Les docs disent:

Une source pseudo-aléatoire déterministe qui génère des nombres aléatoires basés sur un algorithme de mersenne twister. Il s'agit d'une source aléatoire déterministe adaptée à la création de 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 une période plus longue jusqu'à la répétition de séquences. Bien que déterministe, il ne s’agit pas d’une source aléatoire cryptographique. Il convient toutefois pour l'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 Apple: https://github.com/carekit-Apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.Swift

0
Steve Moser

vous pouvez utiliser ce 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)))]
0
M.zar

N'oubliez pas que certains chiffres vont se répéter! alors 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

}
0
Slarty Bartfast