Générer des nombres aléatoires avec Swift


92

J'ai besoin de générer un nombre aléatoire.

Il semble que la arc4randomfonction n'existe plus ainsi que la arc4random_uniformfonction.

Les options que j'ai sont arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int)et arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).

Je ne trouve pas de documentation sur les fonctions et aucun commentaire dans les fichiers d'en-tête ne donne d'indices.


3
Il semblerait que l'auto-complétion dans Xcode soit juste cassée. J'aurais pu jurer que je l'ai tapé sans auto-complétion et qu'il n'a pas été compilé. Travaille maintenant. Belle référence par @arsen
Big_Mac

1
arc4random_uniform est disponible. Il fait partie de l'API Foundation et n'est pas une partie native du langage, vous avez donc besoin d'un "import Foundation" (ou "import UIKit") en tête du fichier pour le rendre disponible.
Vince O'Sullivan

probabilité = Int (arc4random_uniform (UInt32 (total))) - parce que la tête de frappe est cassée, les plaintes de frappe n'étaient pas spécifiques, c'était ma plainte de casting provenant de deux erreurs différentes
bshirley

Réponses:


227

===== 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 que Swift utilise arc4random_bufpour faire son travail.

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

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

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

arc4random_uniform(N)renvoie un nombre aléatoire compris entre 0 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é par rapport aux constructions comme arc4random() % upper_boundcela évite le "biais modulo" lorsque la borne supérieure n'est pas une puissance de deux.


Float.random()est actuellement marqué Beta , et donne ainsi'Float' has no member 'random'
Dale

22

Vous pouvez également essayer:

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

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


1
Quand je regarde cette fonction, je vois public func arc4random_uniform(_: UInt32) -> UInt32. Je me demande donc pourquoi convertir le paramètre en UInt32? Quelque chose d'autre se passe-t-il ici?
Mark Moeykens

8

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

Par exemple, comme randomNumber (MIN: 0, MAX: 10) et vous obtiendrez un nombre compris entre 0 et 9 .

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

Remarque: - Vous obtiendrez toujours en sortie un nombre entier.


1
Je pense que doit être: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

Après quelques recherches, 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 à vous souvenir de l'ensemencement au préalable. J'espère que cela aide quelqu'un: o)


4

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

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, ce n'est pas un générateur de nombres aléatoires cryptographiquement sécurisé .

Vous pouvez l'amorcer à partir de l'heure actuelle ou de toute autre source aléatoire d'entropie. Par exemple, si vous aviez une fonction appelée urand64()qui lit un UInt64from /dev/urandom, vous pouvez l'utiliser comme ceci:

let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
    print(rand())
}

1
let MAX : UInt32 = 9
let MIN : UInt32 = 1 
func randomNumber()
{
   var random_number = Int(arc4random_uniform(MAX) + MIN)
   print ("random = ", random_number);    
}

Pourquoi ne expliquez-vous pas ce code?
réformé

1

Dans Swift 3:

Il générera un nombre aléatoire entre 0 pour limiter

let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")

et si je veux générer un nombre aléatoire de 5 à 10, pas de 0 à n nombre
Rishi

1
@Rishi De 5 à 10 seraitarc4random_uniform(6) + 5
Matt Le Fleur

1

Mon implémentation en tant qu'extension Int. Générera des nombres aléatoires dans la plagefrom..<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

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)))]
}

usage:

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

1

Une autre option consiste à utiliser GKMersenneTwisterRandomSource de GameKit. Les documents 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. Elle est légèrement plus lente qu'une source Arc4, mais plus aléatoire, en ce qu'elle a une période plus longue jusqu'à la répétition des séquences. Bien que déterministe, ce n'est pas une source aléatoire cryptographique. Il convient cependant à 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 d'Apple: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1

Je suis en retard à la fête 🤩🎉

L'utilisation d'une fonction qui vous permet de modifier 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 pour qu'elle soit très concise. Je l'utilise dans tous mes tests de performance / benchmarking.

elementsest le nombre d'éléments du tableau
comprenant uniquement les nombres de0...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

vous pouvez l'utiliser à un 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

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 une sortie au hasard.


0

N'oubliez pas que certains nombres se répéteront! vous devez donc faire quelque chose comme ...

mon totalQuestions était de 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

}

-2

regardez, j'ai eu le même problème mais j'insère la fonction comme une variable globale

comme

var RNumber = Int(arc4random_uniform(9)+1)

func GetCase(){

your code
}

évidemment ce n'est pas efficace, alors je copie et colle simplement le code dans la fonction afin qu'il puisse être réutilisable, puis xcode me suggère de définir la variable 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 crée de toute façon l'application et ce conseil disparaît tout simplement

J'espère que ça aide

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.