Comment générer un nombre aléatoire dans la langue Swift d'Apple?


443

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?

Réponses:


467

Swift 4.2+

Swift 4.2 livré avec Xcode 10 introduit de nouvelles fonctions aléatoires faciles à utiliser pour de nombreux types de données. Vous pouvez appeler la random()méthode sur des types numériques.

let randomInt = Int.random(in: 0..<6)
let randomDouble = Double.random(in: 2.71828...3.14159)
let randomBool = Bool.random()

7
Je n'ai pas eu à importer explicitement Darwin
finneycanhelp

3
Dans mon fichier Playground, j'avais besoin d'importer Darwin parce que je n'importais rien d'autre.
DonnaLea

SoliQuiD: sauf omettre le trait de soulignement supplémentaire après arc4, c'est-à-dire arc4random_uniform (5).
Ali Beadle

3
Avertissement : il a été démontré que RC4 ou arc4 se distingue des valeurs aléatoires pures . Donc, bien que l'arc4 (un chiffrement de flux) semble cryptographiquement sécurisé, ce n'est pas le cas.
Maarten Bodewes

2
@MaartenBodewes: n'est plus directement pertinent pour cette réponse, mais arc4random n'utilise pas réellement le chiffrement RC4, malgré son nom, sur macOS ou les BSD. Il utilise un CSPRNG fourni par le système sur macOS et ChaCha20 sur la plupart des BSD. Le RNG par défaut de Swift (tel qu'utilisé dans cette réponse) l'appelle comme détail d'implémentation sur macOS, mais utilise un générateur sous-jacent approprié sur chaque plate-forme prise en charge.
Stephen Canon

496

À utiliser arc4random_uniform(n)pour un entier aléatoire compris entre 0 et n-1.

let diceRoll = Int(arc4random_uniform(6) + 1)

Castez le résultat sur Int pour ne pas avoir à taper explicitement vos vars en tant que UInt32(ce qui semble non Swifty).


7
Très simple. Je l'aime. Upvote! Mais un vrai dés n'a pas 0. Dans votre code, diceRollpourrait l'être 0. Je dis juste ...
MK Safi

61
Ouais, tu veux vraiment Int(arc4random_uniform(6)+1).
Michael Dorst

5
probabilité = Int (arc4random_uniform (UInt32 (total))) - j'ai aussi dû lancer dans UInt32
bshirley

4
let randomElementInArray = Int (arc4random_uniform (array.count))
cmario

N'oubliez pas de transtyper le paramètre, n, entré en arc3random_uniform(n)a UInt32(n)si vous utilisez une valeur qui n'est pas déjà de ce type.
Dave Fontenot

117

Edit: mis à jour pour Swift 3.0

arc4randomfonctionne bien dans Swift, mais les fonctions de base sont limitées aux types entiers 32 bits ( Int64 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:

public func arc4random<T: ExpressibleByIntegerLiteral>(_ type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, MemoryLayout<T>.size)
    return r
}

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 )

public extension UInt64 {
    public static func random(lower: UInt64 = min, upper: UInt64 = max) -> UInt64 {
        var m: UInt64
        let u = upper - lower
        var r = arc4random(UInt64.self)

        if u > UInt64(Int64.max) {
            m = 1 + ~u
        } else {
            m = ((max - (u * 2)) + 1) % u
        }

        while r < m {
            r = arc4random(UInt64.self)
        }

        return (r % u) + lower
    }
}

Avec cela, nous pouvons étendre Int64pour les mêmes arguments, traitant du débordement:

public extension Int64 {
    public static func random(lower: Int64 = min, upper: Int64 = max) -> Int64 {
        let (s, overflow) = Int64.subtractWithOverflow(upper, lower)
        let u = overflow ? UInt64.max - UInt64(~s) : UInt64(s)
        let r = UInt64.random(upper: u)

        if r > UInt64(Int64.max)  {
            return Int64(r - (UInt64(~lower) + 1))
        } else {
            return Int64(r) + lower
        }
    }
}

Pour compléter la famille ...

private let _wordSize = __WORDSIZE

public extension UInt32 {
    public static func random(lower: UInt32 = min, upper: UInt32 = max) -> UInt32 {
        return arc4random_uniform(upper - lower) + lower
    }
}

public extension Int32 {
    public static func random(lower: Int32 = min, upper: Int32 = max) -> Int32 {
        let r = arc4random_uniform(UInt32(Int64(upper) - Int64(lower)))
        return Int32(Int64(r) + Int64(lower))
    }
}

public extension UInt {
    public static func random(lower: UInt = min, upper: UInt = max) -> UInt {
        switch (_wordSize) {
            case 32: return UInt(UInt32.random(UInt32(lower), upper: UInt32(upper)))
            case 64: return UInt(UInt64.random(UInt64(lower), upper: UInt64(upper)))
            default: return lower
        }
    }
}

public extension Int {
    public static func random(lower: Int = min, upper: Int = max) -> Int {
        switch (_wordSize) {
            case 32: return Int(Int32.random(Int32(lower), upper: Int32(upper)))
            case 64: return Int(Int64.random(Int64(lower), upper: Int64(upper)))
            default: return lower
        }
    }
}

Après tout cela, nous pouvons enfin faire quelque chose comme ça:

let diceRoll = UInt64.random(lower: 1, upper: 7)

Il ne compile pas: var r = arc4random(UInt64). Veuillez conseiller ce que vous vouliez dire ici?
Ossir

@Ossir compile très bien pour moi ... cela signifie appeler la fonction arc4random(définie dans le premier bloc de code) avec l'argument UInt64qui est a Type.
jstn

Arc4random_buf (et donc toutes les extensions 64 bits) souffre-t-il d'un biais modulo?
Matthew Seaman

Le biais Modulo n'entre en jeu que lorsque vous ajoutez une limite supérieure, il ne s'applique donc pas à arc4random_buf. Le but de ces extensions est de faire exactement ce que arc4random_uniformfait (atténuer le biais modulo) sauf pour les types 64 bits.
jstn

lors de l'utilisation des fonctions flottantes, comment puis-je inclure la valeur supérieure dans la gamme de possibilités? Disons donc que je fais 0,0 comme inférieur et 1,0 comme supérieur. Avec cette logique, cela me donnera 0,0 jusqu'à 0,99999999. Mais à la place, j'aimerais inclure le 1.0 comme une possibilité. Comment puis-je atteindre cet objectif?
MobileMon

80

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.

// Generates integers starting with 0 up to, and including, 10
Int.random(in: 0 ... 10)

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 Intvaleur aléatoire entre le minimum et le maximum donnés

func randomInt(min: Int, max: Int) -> Int {
    return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}

61

J'ai utilisé ce code:

var k: Int = random() % 10;

20
vous devez d'abord appeler srandom (UInt32 (time (nil))), sinon il renverra toujours la même séquence de chiffres
Hola Soy Edu Feliz Navidad

3
J'ai lu le document apple sur random () deux fois mais je n'ai pas pu glaner son utilisation ... J'aimerais qu'ils incluent simplement un exemple de code comme celui-ci ci-dessus. "La fonction random () utilise un générateur de nombres aléatoires à rétroaction additive non linéaire, utilisant une table par défaut de longs entiers de taille 31. Elle renvoie des nombres pseudo-aléatoires successifs compris entre 0 et (2 31) -1. La période de ce générateur de nombres aléatoires est très grande, environ 16 * ((2 31) -1). " ... Merci beaucoup Apple ... Je vais être sûr de faire référence à cela dans ma prochaine thèse.
nocarrier

1
random () conduit parfois à un crash soudain sur les iPads. Si cela se produit, utilisez l'arc4random_uniform (6) d'en haut. Si vous utilisez random (), vous pouvez créer plus de valeurs aléatoires en ajoutant srandomdev ().
JackPearse

1
J'ai un message d'erreur du compilateur:random is unavailable in Swift: Use arc4random instead.
Mike Keskinov

1
Cette solution a un biais modulo: zuttobenkyou.wordpress.com/2012/10/18/…
rgov

33

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:

GKRandomSource.sharedRandom().nextInt()

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:

GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

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:

let d6 = GKRandomDistribution.d6()
d6.nextInt()

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 .


1
Merci pour cette astuce, c'est l'une des meilleures réponses. Pour utiliser ces fonctions, il faut ajouter import GameplayKit. Swift 3 a changé la syntaxe enGKRandomSource.sharedRandom().nextInt(upperBound: 6)
petrsyn

7
quel est le poids de ce kit à importer? je ne veux pas gonfler mon code.
μολὼν.λαβέ

25

Vous pouvez le faire de la même manière que vous le feriez en C:

let randomNumber = arc4random()

randomNumberest supposé être de type UInt32(un entier non signé 32 bits)


12
Addendum: rand, arc4random, drand48et amis sont tous dans le Darwinmodule. Il est déjà importé pour vous si vous créez une application Cocoa, UIKit ou Foundation, mais vous en aurez besoin import Darwindans les aires de jeux.
rickster

5
Et n'essayez pas de convertir le résultat de arc4random () en un Int - cela fonctionnera bien sur une plate-forme 64 bits, mais sur une plate-forme 32 bits, les Ints sont signés 32 bits, donc vous obtiendrez un négatif inattendu Nombres. Cela a déjà déclenché quelques personnes, alors j'ai pensé que je le mentionnerais ici.
Matt Gibson

23

Utilisation arc4random_uniform()

Usage:

arc4random_uniform(someNumber: UInt32) -> UInt32

Cela vous donne des entiers aléatoires dans la plage 0de someNumber - 1.

La valeur maximale pour UInt32est de 4 294 967 295 (c'est-à-dire 2^32 - 1).

Exemples:

  • Tirage au sort

    let flip = arc4random_uniform(2) // 0 or 1
  • Lancer de dés

    let roll = arc4random_uniform(6) + 1 // 1...6
  • Jour aléatoire en octobre

    let day = arc4random_uniform(31) + 1 // 1...31
  • Année aléatoire dans les années 1990

    let year = 1990 + arc4random_uniform(10)

Forme générale:

let number = min + arc4random_uniform(max - min + 1)

number, maxet minsont UInt32.

Qu'en est-il de...

arc4random ()

Vous pouvez également obtenir un nombre aléatoire en utilisant arc4random(), ce qui produit UInt32entre 0 et 2 ^ 32-1. Ainsi, pour obtenir un nombre aléatoire entre 0et x-1, vous pouvez le diviser par xet prendre le reste. Ou en d'autres termes, utilisez l' opérateur restant (%) :

let number = arc4random() % 5 // 0...4

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 Intet UInt32:

let number: Int = 10
let random = Int(arc4random_uniform(UInt32(number)))

Le problème, cependant, est qu'il Inta une gamme de -2,147,483,648...2,147,483,647systèmes 32 bits et une gamme de -9,223,372,036,854,775,808...9,223,372,036,854,775,807systèmes 64 bits. Comparez cela à la UInt32gamme de 0...4,294,967,295. Le Ude UInt32signifie non signé .

Considérez les erreurs suivantes:

UInt32(-1) // negative numbers cause integer overflow error
UInt32(4294967296) // numbers greater than 4,294,967,295 cause integer overflow error

Il vous suffit donc de vous assurer que vos paramètres d'entrée se situent dans la UInt32plage et que vous n'avez pas besoin non plus d'une sortie en dehors de cette plage.


19

Exemple pour un nombre aléatoire entre 10 (0-9);

import UIKit

let randomNumber = Int(arc4random_uniform(10))

Code très facile - simple et court.


16

J'ai pu simplement utiliser rand()pour obtenir un CInt aléatoire. Vous pouvez en faire un Int en utilisant quelque chose comme ceci:

let myVar: Int = Int(rand())

Vous pouvez utiliser votre fonction aléatoire C préférée et simplement la convertir en valeur en Int si nécessaire.


Ouais, la conversion de type peut être une entreprise délicate dans le cas contraire et laisser le constructeur Int y faire face est un véritable épargnant de douleur.
Kzrbill

4
Notez que si vous n'appelez pas srand (...) (appelez-le une seule fois) avant d'utiliser rand (), la séquence de nombres sera toujours exactement la même entre chaque exécution de votre programme. Si vous ne le souhaitez pas, utilisez arc4random ()
SomeGuy

2
Vous pouvez également utiliser random(), qui renvoie un Intplutôt que UInt32- et comme @SomeGuy l'a mentionné, appelez simplement srandom(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.
brittlewis12

1
Quelqu'un peut-il commenter rand () vs arc4random_uniform ()?
Ruben Martinez Jr.

16

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.

public extension ExpressibleByIntegerLiteral {
    public static func arc4random() -> Self {
        var r: Self = 0
        arc4random_buf(&r, MemoryLayout<Self>.size)
        return r
    }
}

Maintenant, nous pouvons faire:

let i = Int.arc4random()
let j = UInt32.arc4random()

et toutes les autres classes entières sont correctes.


11

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és

let randInt = Int.random(in: 1..<10)

Aussi avec d'autres types

let randFloat = Float.random(in: 1..<20)
let randDouble = Double.random(in: 1...30)
let randCGFloat = CGFloat.random(in: 1...40)

9

Voici une bibliothèque qui fait bien le travail https://github.com/thellimist/SwiftRandom

public extension Int {
    /// SwiftRandom extension
    public static func random(lower: Int = 0, _ upper: Int = 100) -> Int {
        return lower + Int(arc4random_uniform(UInt32(upper - lower + 1)))
    }
}

public extension Double {
    /// SwiftRandom extension
    public static func random(lower: Double = 0, _ upper: Double = 100) -> Double {
        return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
    }
}

public extension Float {
    /// SwiftRandom extension
    public static func random(lower: Float = 0, _ upper: Float = 100) -> Float {
        return (Float(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower
    }
}

public extension CGFloat {
    /// SwiftRandom extension
    public static func random(lower: CGFloat = 0, _ upper: CGFloat = 1) -> CGFloat {
        return CGFloat(Float(arc4random()) / Float(UINT32_MAX)) * (upper - lower) + lower
    }
}

8
 let MAX : UInt32 = 9
 let MIN : UInt32 = 1

    func randomNumber()
{
    var random_number = Int(arc4random_uniform(MAX) + MIN)
    print ("random = ", random_number);
}

6

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 de SecCopyRandomBytes()toute façon, même si votre besoin ne le fait pas '' t tout à fait exiger cela.


6

Depuis Swift 4.2

Il existe un nouvel ensemble d'API:

let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomDouble = Double.random(in: 1 ... 10)
  • Tous les types numériques ont désormais la random(in:)méthode qui prend range.

  • 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?

  1. Vous devez utiliser des API C importées (elles sont différentes entre les plates-formes) .

  2. Et de plus...

Et si je vous disais que le hasard n'est pas si aléatoire?

Si vous utilisez arc4random() (pour calculer le reste) comme arc4random() % aNumber, le résultat n'est pas uniformément réparti entre le 0et aNumber. Il existe un problème appelé biais Modulo .

Biais modulo

Normalement, la fonction génère un nombre aléatoire entre 0et MAX (dépend du type, etc.) . Pour faire un exemple rapide et facile, disons que le nombre maximum est 7et que vous vous souciez d'un nombre aléatoire dans la plage 0 ..< 2 (ou l'intervalle [0, 3) si vous préférez) .

Les probabilités pour les nombres individuels sont:

  • 0: 3/8 = 37,5%
  • 1: 3/8 = 37,5%
  • 2: 2/8 = 25%

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".

Ce problème est résolu par SE-0202 - Unification aléatoire dans Swift 4.2


5

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

import GameplayKit

alors

let diceRoll = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

5
var randomNumber = Int(arc4random_uniform(UInt32(5)))

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.


1
Si vous passez 5, il retournera 5 résultats possibles de zéro à quatre. 0 ... 4
Leo Dabus

3

Swift 4.2

Au revoir pour importer Foundation C lib arc4random_uniform()

// 1  
let digit = Int.random(in: 0..<10)

// 2
if let anotherDigit = (0..<10).randomElement() {
  print(anotherDigit)
} else {
  print("Empty range.")
}

// 3
let double = Double.random(in: 0..<1)
let float = Float.random(in: 0..<1)
let cgFloat = CGFloat.random(in: 0..<1)
let bool = Bool.random()
  1. Vous utilisez random (in :) pour générer des chiffres aléatoires à partir des plages.
  2. randomElement () renvoie nil si la plage est vide, vous déballez donc l'int avec si laisser.
  3. Vous utilisez random (in :) pour générer un Double, Float ou CGFloat aléatoire et random () pour renvoyer un Bool aléatoire.

Plus @ officiel


2

Le code suivant produira un nombre aléatoire sécurisé compris entre 0 et 255:

extension UInt8 {
  public static var random: UInt8 {
    var number: UInt8 = 0
    _ = SecRandomCopyBytes(kSecRandomDefault, 1, &number)
    return number
  }
}

Vous l'appelez comme ceci:

print(UInt8.random)

Pour les plus grands nombres, cela devient plus compliqué.
C'est le mieux que j'ai pu trouver:

extension UInt16 {
  public static var random: UInt16 {
    let count = Int(UInt8.random % 2) + 1
    var numbers = [UInt8](repeating: 0, count: 2)
    _ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
    return numbers.reversed().reduce(0) { $0 << 8 + UInt16($1) }
  }
}

extension UInt32 {
  public static var random: UInt32 {
    let count = Int(UInt8.random % 4) + 1
    var numbers = [UInt8](repeating: 0, count: 4)
    _ = SecRandomCopyBytes(kSecRandomDefault, count, &numbers)
    return numbers.reversed().reduce(0) { $0 << 8 + UInt32($1) }
  }
}

Ces méthodes utilisent un nombre aléatoire supplémentaire pour déterminer combien de UInt8s vont être utilisés pour créer le nombre aléatoire. La dernière ligne convertit le [UInt8]en UInt16ouUInt32 .

Je ne sais pas si les deux derniers comptent toujours comme vraiment aléatoires, mais vous pouvez le modifier à votre guise :)


Vous avez habilement évité le biais introduit par modulo, +1 pour cela. Vous pourriez avertir les lecteurs pourquoi vous l'avez fait.
2017

C'est intéressant, je n'ai pas vraiment considéré que le biais modulo pouvait être en jeu ici. Peut-être que les chances d'obtenir un petit nombre ne sont pas les mêmes que d'obtenir un grand nombre.
Zyphrax

2

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 )

let intBetween0to9 = Int.random(in: 0...9) 
let doubleBetween0to1 = Double.random(in: 0...1)

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


1

Swift 4.2, Xcode 10.1 .

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 la GKRandomSourceclasse avec sa sharedRandom()méthode de classe:

import GameKit

let number: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

func randomGenerator() -> Int {
    let random = GKRandomSource.sharedRandom().nextInt(upperBound: number.count)
    return number[random]
}
randomGenerator()

Ou utilisez simplement une randomElement()méthode qui renvoie un élément aléatoire de la collection:

let number: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let randomNumber = number.randomElement()!
print(randomNumber)

0

Vous pouvez utiliser GeneratorOfcomme ceci:

var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
    _ -> Int? in
    fibs.append(fibs.reduce(0, combine:+))
    return fibs.removeAtIndex(0)
}

println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())

3
Comment Fibonacci est-il aléatoire?
Nikolai Ruhe

Salut Nikolai, Ce bloc de code est l'ancienne version Swift 1.2. Si vous essayez un nouveau Swift 2.0. Ce ne serait pas du travail.
Durul Dalkanat

2
Je comprends, mais ça ressemble toujours à un générateur de fibonacci, pas des nombres aléatoires, comme demandé dans la question.
Nikolai Ruhe

0

J'utilise ce code pour générer un nombre aléatoire:

//
//  FactModel.swift
//  Collection
//
//  Created by Ahmadreza Shamimi on 6/11/16.
//  Copyright © 2016 Ahmadreza Shamimi. All rights reserved.
//

import GameKit

struct FactModel {

    let fun  = ["I love swift","My name is Ahmadreza","I love coding" ,"I love PHP","My name is ALireza","I love Coding too"]


    func getRandomNumber() -> String {

        let randomNumber  = GKRandomSource.sharedRandom().nextIntWithUpperBound(fun.count)

        return fun[randomNumber]
    }
}

2
Bienvenue chez SO. Les réponses codées uniquement sont déconseillées - veuillez modifier votre réponse pour expliquer pourquoi ce code répond à la question et comment il fonctionne. Voir stackoverflow.com/help/how-to-answer pour plus d'informations.
Tim Malone

2
Veuillez fournir un peu de contexte autour de votre réponse et bienvenue dans stackoverflow. :)
Jonathan Eustace

0

Détails

xCode 9.1, Swift 4

Solution orientée mathématique (1)

import Foundation

class Random {

    subscript<T>(_ min: T, _ max: T) -> T where T : BinaryInteger {
        get {
            return rand(min-1, max+1)
        }
    }
}

let rand = Random()

func rand<T>(_ min: T, _ max: T) -> T where T : BinaryInteger {
    let _min = min + 1
    let difference = max - _min
    return T(arc4random_uniform(UInt32(difference))) + _min
}

Utilisation de la solution (1)

let x = rand(-5, 5)       // x = [-4, -3, -2, -1, 0, 1, 2, 3, 4]
let x = rand[0, 10]       // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Solution orientée programmeurs (2)

N'oubliez pas d' ajouter ici du code de solution orientée mathématique (1)

import Foundation

extension CountableRange where Bound : BinaryInteger {

    var random: Bound {
        return rand(lowerBound-1, upperBound)
    }
}

extension CountableClosedRange where Bound : BinaryInteger {

    var random: Bound {
        return rand[lowerBound, upperBound]
    }
}

Utilisation de la solution (2)

let x = (-8..<2).random           // x = [-8, -7, -6, -5, -4, -3, -2, -1, 0, 1]
let x = (0..<10).random           // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let x = (-10 ... -2).random       // x = [-10, -9, -8, -7, -6, -5, -4, -3, -2]

Échantillon complet

N'oubliez pas d' ajouter ici les codes solution (1) et solution (2)

private func generateRandNums(closure:()->(Int)) {

    var allNums = Set<Int>()
    for _ in 0..<100 {
        allNums.insert(closure())
    }
    print(allNums.sorted{ $0 < $1 })
}

generateRandNums {
    (-8..<2).random
}

generateRandNums {
    (0..<10).random
}

generateRandNums {
    (-10 ... -2).random
}

generateRandNums {
    rand(-5, 5)
}
generateRandNums {
    rand[0, 10]
}

Exemple de résultat

entrez la description de l'image ici


2
Cette réponse est hors sujet. La question était de savoir comment générer un nombre aléatoire. Pas comment faire une bibliothèque de nombres aléatoires. Sheesh.
Andrew Paul Simmons
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.