Come si genera un numero casuale nella lingua Swift di Apple?


443

Mi rendo conto che il libro Swift ha fornito un'implementazione di un generatore di numeri casuali. È la migliore pratica copiare e incollare questa implementazione nel proprio programma? O c'è una libreria che fa questo che possiamo usare ora?

Risposte:


467

Swift 4.2+

Swift 4.2 fornito con Xcode 10 introduce nuove funzioni casuali facili da usare per molti tipi di dati. È possibile chiamare il random()metodo su tipi numerici.

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

7
Non ho dovuto importare esplicitamente Darwin
finneycanhelp il

3
Nel mio file Playground dovevo importare Darwin perché non stavo importando nient'altro.
DonnaLea

SoliQuiD: tranne omettere il carattere di sottolineatura extra dopo arc4, ovvero arc4random_uniform (5).
Ali Beadle,

3
Avvertenza : RC4 o arc4 hanno dimostrato di essere distinguibili dai valori casuali puri . Quindi, sebbene arc4 (un codice di flusso) suona crittograficamente sicuro, in realtà non lo è.
Maarten Bodewes,

2
@MaartenBodewes: non è più direttamente pertinente a questa risposta, ma arc4random in realtà non utilizza la cifra RC4, nonostante il suo nome, su macOS o BSD. Utilizza un CSPRNG fornito dal sistema su macOS e ChaCha20 sulla maggior parte dei BSD. L'RNG predefinito di Swift (come utilizzato in questa risposta) lo chiama come dettaglio di implementazione su macOS, ma utilizza un generatore sottostante appropriato su ciascuna piattaforma supportata.
Stephen Canon,

496

Utilizzare arc4random_uniform(n)per un numero intero casuale compreso tra 0 e n-1.

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

Trasmetti il ​​risultato a Int in modo da non dover digitare esplicitamente i tuoi parametri come UInt32(che sembra non Swifty).


7
Molto semplice. Mi piace. Upvote! Ma un vero dado non ha 0. Nel tuo codice, diceRollpotrebbe essere 0. Sto solo dicendo ...
MK Safi,

61
Sì, lo vuoi davvero Int(arc4random_uniform(6)+1).
Michael Dorst,

5
probabilità = Int (arc4random_uniform (UInt32 (totale))) - dovevo anche lanciare UInt32
bshirley

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

Non dimenticare di trasmettere il parametro, n, inserito in arc3random_uniform(n)a UInt32(n)se stai utilizzando un valore che non è già di quel tipo.
Dave Fontenot,

117

Modifica: aggiornato per Swift 3.0

arc4random funziona bene in Swift, ma le funzioni di base sono limitate ai tipi interi a 32 bit (Int è a 64 bit su iPhone 5S e Mac moderni). Ecco una funzione generica per un numero casuale di un tipo esprimibile da un intero letterale:

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

Possiamo usare questa nuova funzione generica per estendere UInt64, aggiungere argomenti al contorno e mitigare la distorsione del modulo. (Viene sollevato direttamente da 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
    }
}

Con ciò possiamo estendere Int64 gli stessi argomenti, trattando l'overflow:

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

Per completare la famiglia ...

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

Dopo tutto ciò, possiamo finalmente fare qualcosa del genere:

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

Esso non può essere compilato: var r = arc4random(UInt64). Per favore, cosa intendi qui?
Ossir,

@Ossir compila bene per me ... significa chiamare la funzione arc4random(definita nel primo blocco di codice) con l'argomento UInt64che è a Type.
jn

Arc4random_buf (e quindi tutte le estensioni a 64 bit) soffre di distorsioni del modulo?
Matthew Seaman,

La polarizzazione di Modulo entra in gioco solo quando aggiungi un limite superiore, quindi non si applica a arc4random_buf. Lo scopo di queste estensioni è fare esattamente ciò che arc4random_uniformfa (mitigare il bias del modulo) ad eccezione dei tipi a 64 bit.
JN

quando si usano le funzioni float, come posso includere il valore superiore nella gamma di possibilità? Quindi diciamo che faccio 0.0 come inferiore e 1.0 come superiore. Con questa logica mi darà 0,0 fino a 0.99999999. Ma invece vorrei includere 1.0 come possibilità. Come posso raggiungere questo obiettivo?
MobileMon,

80

Modifica per Swift 4.2

A partire da Swift 4.2, invece di utilizzare la funzione C importata arc4random_uniform (), ora puoi utilizzare le funzioni native di Swift.

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

Puoi usare random(in:)per ottenere valori casuali anche per altri valori primitivi; come Int, Double, Float e persino Bool.

Versioni veloci <4.2

Questo metodo genererà un Intvalore casuale tra il minimo e il massimo indicati

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

61

Ho usato questo codice:

var k: Int = random() % 10;

20
devi prima chiamare srandom (UInt32 (time (nil))), altrimenti restituirà sempre la stessa sequenza numerica
Hola Soy Edu Feliz Navidad

3
Ho letto il documento Apple su random () due volte ma non sono riuscito a comprenderne l'utilizzo ... Vorrei che includessero semplicemente un esempio di codice come questo sopra. "La funzione random () utilizza un feedback additivo non lineare, generatore di numeri casuali, che utilizza una tabella predefinita di interi lunghi di dimensione 31. Restituisce numeri pseudo-casuali successivi nell'intervallo da 0 a (2 31) -1. il periodo di questo generatore di numeri casuali è molto grande, circa 16 * ((2 31) -1). " ... Grazie mille mela ... Sarò sicuro di fare riferimento a questo nella mia prossima tesi.
nocarrier,

1
random () a volte porta a un arresto improvviso su iPad. In tal caso, utilizzare arc4random_uniform (6) dall'alto. Se usi random (), puoi creare più valori casuali anteponendo srandomdev ().
JackPearse,

1
Ho ricevuto il messaggio di errore del compilatore:random is unavailable in Swift: Use arc4random instead.
Mike Keskinov,

1
Questa soluzione ha una distorsione da modulo: zuttobenkyou.wordpress.com/2012/10/18/…
rgov

33

A partire da iOS 9, puoi utilizzare le nuove classi GameplayKit per generare numeri casuali in vari modi.

Puoi scegliere tra quattro tipi di sorgente: una fonte casuale generale (senza nome, fino al sistema per scegliere cosa fare), lineare congruenziale, ARC4 e Mersenne Twister. Questi possono generare ints, float e bool casuali.

Al livello più semplice, è possibile generare un numero casuale dalla fonte casuale incorporata del sistema in questo modo:

GKRandomSource.sharedRandom().nextInt()

Ciò genera un numero compreso tra -2.147.483.648 e 2.147.483.647. Se si desidera un numero compreso tra 0 e un limite superiore (esclusivo), utilizzare questo:

GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

GameplayKit ha alcuni costruttori di convenienza integrati per lavorare con i dadi. Ad esempio, puoi tirare un dado a sei facce in questo modo:

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

Inoltre puoi modellare la distribuzione casuale usando cose come GKShuffledDistribution. Questo richiede un po 'più di spiegazione, ma se sei interessato puoi leggere il mio tutorial su GameplayKit numeri casuali .


1
Grazie per questo suggerimento, è una delle migliori risposte. Per utilizzare queste funzioni è necessario aggiungere import GameplayKit. Swift 3 ha cambiato la sintassi inGKRandomSource.sharedRandom().nextInt(upperBound: 6)
petrsyn il

7
quanto costa importare questo kit? non voglio gonfiare il mio codice.
μολὼν.λαβέ

25

Puoi farlo nello stesso modo in cui lo faresti in C:

let randomNumber = arc4random()

randomNumberviene considerato di tipo UInt32(un numero intero senza segno a 32 bit)


12
Addendum: rand, arc4random, drand48e gli amici sono tutti nel Darwinmodulo. È già importato per te se stai costruendo un'app Cocoa, UIKit o Foundation, ma dovrai farlo import Darwinnei parchi giochi.
rickster

5
E non tentare di trasmettere il risultato di arc4random () a un Int: questo funzionerà perfettamente su una piattaforma a 64 bit, ma su una piattaforma a 32 bit, gli Ints sono firmati a 32 bit, quindi otterrai un imprevisto negativo numeri. Questo ha già fatto scattare alcune persone, quindi ho pensato di menzionarlo qui.
Matt Gibson,

23

Uso arc4random_uniform()

Uso:

arc4random_uniform(someNumber: UInt32) -> UInt32

Questo ti dà numeri casuali nell'intervallo 0a someNumber - 1.

Il valore massimo per UInt32è 4.294.967.295 (ovvero, 2^32 - 1).

Esempi:

  • Testa o croce

    let flip = arc4random_uniform(2) // 0 or 1
  • Rotolo di dadi

    let roll = arc4random_uniform(6) + 1 // 1...6
  • Giornata casuale ad ottobre

    let day = arc4random_uniform(31) + 1 // 1...31
  • Anno casuale negli anni '90

    let year = 1990 + arc4random_uniform(10)

Forma generale:

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

dove number, maxe minsono UInt32.

Che dire...

arc4random ()

Puoi anche ottenere un numero casuale usando arc4random(), che produce UInt32tra 0 e 2 ^ 32-1. Pertanto, per ottenere un numero casuale tra 0e x-1, puoi dividerlo per xe prendere il resto. O in altre parole, utilizzare l' operatore Remainder (%) :

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

Tuttavia, questo produce una leggera distorsione del modulo (vedi anche qui e qui ), quindi è per questo che arc4random_uniform()è raccomandato.

Conversione da e verso Int

Normalmente sarebbe bene fare qualcosa del genere per convertire avanti e indietro tra Inte UInt32:

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

Il problema, tuttavia, è che Intha una gamma di -2,147,483,648...2,147,483,647sistemi a 32 bit e una gamma di -9,223,372,036,854,775,808...9,223,372,036,854,775,807sistemi a 64 bit. Confronta questo con la UInt32gamma di 0...4,294,967,295. Il Udi UInt32significa non firmato .

Considera i seguenti errori:

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

Quindi devi solo essere sicuro che i tuoi parametri di input siano all'interno UInt32dell'intervallo e che non ti serva nemmeno un output al di fuori di tale intervallo.


19

Esempio di numero casuale compreso tra 10 (0-9);

import UIKit

let randomNumber = Int(arc4random_uniform(10))

Codice molto semplice: semplice e breve.


16

Sono stato in grado di utilizzare solo rand()per ottenere un CInt casuale. Puoi renderlo un Int usando qualcosa del genere:

let myVar: Int = Int(rand())

Puoi usare la tua funzione casuale C preferita e, se necessario, convertire semplicemente in valore in Int.


Sì, altrimenti la conversione dei tipi può essere un affare complicato e lasciare che il costruttore Int lo gestisca è un vero risparmio di dolore.
Kzrbill,

4
Nota che se non stai chiamando srand (...) (chiamalo una volta sola) prima di usare rand (), la sequenza di numeri sarà sempre la stessa tra ogni esecuzione del tuo programma. Se non lo desideri, utilizza arc4random ()
SomeGuy il

2
Potresti anche usare random(), che restituisce un Intpiuttosto che UInt32- e come menzionato da @SomeGuy, semplicemente chiama srandom(arc4random())una volta ovunque prima di usarlo per assicurarti che abbia un seme diverso e randomizzato per ogni esecuzione del tuo programma.
brittlewis12,

1
Qualcuno può commentare su rand () vs arc4random_uniform ()?
Ruben Martinez Jr.

16

La risposta di @ jstn è buona, ma un po 'dettagliata. Swift è noto come linguaggio orientato al protocollo, quindi possiamo ottenere lo stesso risultato senza dover implementare il codice boilerplate per ogni classe nella famiglia di interi, aggiungendo un'implementazione predefinita per l'estensione del protocollo.

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

Ora possiamo fare:

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

e tutte le altre classi di numeri interi sono ok.


11

In Swift 4.2 è possibile generare numeri casuali chiamando il random()metodo su qualsiasi tipo numerico desiderato, fornendo l'intervallo con cui si desidera lavorare. Ad esempio, questo genera un numero casuale nell'intervallo da 1 a 9, incluso su entrambi i lati

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

Anche con altri tipi

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

9

Ecco una libreria che fa bene il lavoro 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

Vorrei aggiungere alle risposte esistenti che l'esempio di generatore di numeri casuali nel libro di Swift è un generatore di congruenza lineare (LCG), è un modello fortemente limitato e non dovrebbe essere, tranne per gli esempi banali, in cui la qualità della casualità non non importa affatto. E un LCG non dovrebbe mai essere usato per scopi crittografici .

arc4random() è molto meglio e può essere utilizzato per la maggior parte degli scopi, ma di nuovo non dovrebbe essere usato per scopi crittografici.

Se vuoi qualcosa che sia garantito crittograficamente sicuro, usa SecCopyRandomBytes(). Nota che se costruisci un generatore di numeri casuali in qualcosa, qualcun altro potrebbe finire (mis) usandolo per scopi crittografici (come password, generazione di chiavi o sale), allora dovresti considerare di usare SecCopyRandomBytes()comunque, anche se le tue necessità non lo fanno ' Non è assolutamente necessario.


6

Da Swift 4.2

Esiste un nuovo set di API:

let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomDouble = Double.random(in: 1 ... 10)
  • Tutti i tipi numerici ora hanno il random(in:)metodo che richiede range.

  • Restituisce un numero uniformemente distribuito in quell'intervallo.


TL; DR

Bene, cosa c'è di sbagliato nel vecchio "buono" modo?

  1. Devi usare le API C importate (sono diverse tra le piattaforme) .

  2. Ed inoltre...

E se ti dicessi che il casuale non è così casuale?

Se si utilizza arc4random() (per calcolare il resto) come arc4random() % aNumber, il risultato non viene distribuito uniformemente tra 0e aNumber. Si è verificato un problema chiamato distorsione modulo .

Distorsione da modulo

Normalmente, la funzione genera un numero casuale compreso tra 0e MAX (dipende dal tipo ecc . ) . Per fare un esempio semplice e veloce, supponiamo che il numero massimo sia 7e ti preoccupi di un numero casuale nell'intervallo 0 ..< 2 (o nell'intervallo [0, 3) se lo preferisci) .

Le probabilità per i singoli numeri sono:

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

In altre parole, è più probabile che finisca con 0 o 1 rispetto a 2 . Naturalmente, tieni presente che questo è estremamente semplificato e il numero MAX è molto più alto, rendendolo più "equo".

Questo problema viene risolto da SE-0202 - Unificazione casuale in Swift 4.2


5

Senza arc4Random_uniform () in alcune versioni di Xcode (in 7.1 funziona ma non si completa automaticamente per me). Puoi farlo invece.

Per generare un numero casuale da 0-5. Primo

import GameplayKit

Poi

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

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

Qui 5 si assicurerà che il numero casuale sia generato da zero a quattro. È possibile impostare il valore di conseguenza.


1
Se passi 5, restituirà 5 possibili risultati da zero a quattro. 0 ... 4
Leo Dabus,

3

Rapido 4.2

Arrivederci per importare 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. Si utilizza random (in :) per generare cifre casuali dagli intervalli.
  2. randomElement () restituisce zero se l'intervallo è vuoto, in modo da scartare Int restituito? con if let.
  3. Si utilizza random (in :) per generare un Double, Float o CGFloat casuale e random () per restituire un Bool casuale.

Altro @ Ufficiale


2

Il seguente codice produrrà un numero casuale sicuro compreso tra 0 e 255:

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

Lo chiami così:

print(UInt8.random)

Per numeri più grandi diventa più complicato.
Questo è il meglio che ho potuto inventare:

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

Questi metodi utilizzano un numero casuale aggiuntivo per determinare quanti UInt8s verranno utilizzati per creare il numero casuale. L'ultima riga converte [UInt8]in UInt16oUInt32 .

Non so se gli ultimi due contano ancora come casuali, ma puoi modificarlo a tuo piacimento :)


Hai evitato abilmente la distorsione introdotta da modulo, +1 per questo. Potresti avvertire i lettori perché l'hai fatto.
jww

È interessante, non ho davvero considerato che la distorsione del modulo potrebbe essere in gioco qui. Forse le possibilità di ottenere un numero piccolo non sono le stesse di ottenere un numero elevato.
Zyphrax,

2

Rapido 4.2

Swift 4.2 ha incluso un'API per numeri casuali nativa e abbastanza completa nella libreria standard. ( Proposta Swift Evolution SE-0202 )

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

Tutti i tipi di numero hanno il random statico (in :) che accetta l'intervallo e restituisce il numero casuale nell'intervallo specificato


1

Swift 4.2, Xcode 10.1 .

Per iOS, macOS e tvOS è possibile utilizzare l'origine casuale a livello di sistema nel framework di Xcode GameKit. Qui puoi trovare la GKRandomSourceclasse con il suo sharedRandom()metodo class:

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

O semplicemente usa un randomElement()metodo che restituisce un elemento casuale della raccolta:

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

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

0

Puoi usare GeneratorOfcosì:

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
Com'è casuale Fibonacci?
Nikolai Ruhe,

Ciao Nikolai, questo blocco di codice è la vecchia versione Swift 1.2. Se provi il nuovo Swift 2.0. Non sarebbe lavoro.
Durul Dalkanat,

2
Capisco, ma mi sembra comunque un generatore di fibonacci, non numeri casuali, come richiesto nella domanda.
Nikolai Ruhe,

0

Uso questo codice per generare un numero casuale:

//
//  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
Benvenuti in SO. Le risposte al solo codice sono sconsigliate: modifica la tua risposta per spiegare perché questo codice risponde alla domanda e come funziona. Vedi stackoverflow.com/help/how-to-answer per ulteriori informazioni.
Tim Malone,

2
Fornisci un contesto sulla risposta e benvenuto su StackOverflow. :)
Jonathan Eustace,

0

Dettagli

xCode 9.1, Swift 4

Soluzione orientata alla matematica (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
}

Utilizzo della soluzione (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]

Soluzione orientata ai programmatori (2)

Non dimenticare di aggiungere qui il codice della soluzione orientata alla matematica (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]
    }
}

Utilizzo della soluzione (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]

Campione completo

Non dimenticare di aggiungere qui i codici soluzione (1) e soluzione (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]
}

Risultato del campione

inserisci qui la descrizione dell'immagine


2
Questa risposta è fuori tema. La domanda era come generare un numero casuale. Non come creare una libreria di numeri casuali. Sheesh.
Andrew Paul Simmons,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.