Jak wygenerować liczbę losową w języku Swift firmy Apple?


443

Zdaję sobie sprawę, że książka Swift zapewnia implementację generatora liczb losowych. Czy najlepszą praktyką jest kopiowanie i wklejanie tej implementacji we własnym programie? A może jest biblioteka, z której możemy teraz korzystać?

Odpowiedzi:


466

Swift 4.2+

Swift 4.2 dostarczany z Xcode 10 wprowadza nowe łatwe w użyciu losowe funkcje dla wielu typów danych. Możesz wywołać tę random()metodę dla typów numerycznych.

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

7
Nie musiałem wyraźnie importować Darwina
finneycanhelp

3
W moim pliku Playground musiałem zaimportować Darwina, ponieważ nie importowałem niczego innego.
DonnaLea,

SoliQuiD: z wyjątkiem pominięcia dodatkowego podkreślenia po arc4, tj. Arc4random_uniform (5).
Ali Beadle,

3
Ostrzeżenie : wykazano, że RC4 lub arc4 można odróżnić od czysto losowych wartości . Więc chociaż arc4 (szyfr strumieniowy) wydaje się kryptograficznie bezpieczny, tak naprawdę nie jest.
Maarten Bodewes

2
@ MaartenBodewes: nie ma już bezpośredniego związku z tą odpowiedzią, ale arc4random tak naprawdę nie używa szyfru RC4, pomimo swojej nazwy, na macOS lub BSD. Używa dostarczonego przez system CSPRNG na macOS i ChaCha20 na większości BSD. Domyślny RNG Swifta (użyty w tej odpowiedzi) nazywa go jako szczegół implementacji na macOS, ale używa odpowiedniego generatora na każdej obsługiwanej platformie.
Stephen Canon

496

Użyj arc4random_uniform(n)dla losowej liczby całkowitej od 0 do n-1.

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

Rzuć wynik na Int, abyś nie musiał jawnie wpisywać swoich warów jako UInt32(co wydaje się nie-Swifty).


7
Bardzo prosta. Lubię to. Głosuj! Ale rzeczywiste kości nie mają 0. W twoim kodzie diceRollmoże być 0. Tylko mówię ...
MK Safi

61
Tak, naprawdę chcesz Int(arc4random_uniform(6)+1).
Michael Dorst

5
prawdopodobieństwo = Int (arc4random_uniform (UInt32 (ogółem))) - musiałem też rzucić na UInt32
bshirley

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

Nie zapomnij rzucić parametru n wprowadzonego na arc3random_uniform(n)a, UInt32(n)jeśli używasz wartości, która nie jest jeszcze tego typu.
Dave Fontenot

117

Edycja: Zaktualizowano dla Swift 3.0

arc4randomdziała dobrze w Swift, ale podstawowe funkcje są ograniczone do 32-bitowych liczb całkowitych ( Int64-bit na iPhone 5S i współczesnych komputerach Mac). Oto ogólna funkcja dla losowej liczby typu wyrażanego literałami całkowitymi:

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

Możemy użyć tej nowej funkcji ogólnej do rozszerzenia UInt64, dodania argumentów granicznych i złagodzenia błędu modulo. (To jest podnoszone prosto z 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
    }
}

Dzięki temu możemy przedłużyć Int64 o te same argumenty, zajmując się przepełnieniem:

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

Aby uzupełnić rodzinę ...

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

Po tym wszystkim możemy wreszcie zrobić coś takiego:

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

To nie kompilacji: var r = arc4random(UInt64). Proszę o poradę, co miałeś na myśli?
Ossir,

@Ossir kompiluje się dobrze dla mnie ... oznacza to wywołanie funkcji arc4random(zdefiniowanej w pierwszym bloku kodu) z argumentem, UInt64który jest Type.
jstn

Czy arc4random_buf (a zatem wszystkie 64-bitowe rozszerzenia) cierpi na błąd modulo?
Matthew Seaman

Odchylenie modulo wchodzi w grę dopiero po dodaniu górnej granicy, więc nie ma zastosowania arc4random_buf. Celem tych rozszerzeń jest robienie dokładnie tego, co arc4random_uniformrobi (łagodzenie błędu modulo), z wyjątkiem typów 64-bitowych.
jstn

w przypadku korzystania z funkcji pływaka, jak mogę zawrzeć górną wartość w zakresie możliwości? Powiedzmy, że wykonuję 0,0 jako dolną i 1,0 jako górną. Dzięki tej logice da mi 0,0 do 0,99999999. Zamiast tego chciałbym uwzględnić 1.0 jako opcję. Jak mogę to osiągnąć?
MobileMon,

80

Edycja dla Swift 4.2

Począwszy od Swift 4.2, zamiast korzystać z importowanej funkcji C arc4random_uniform (), możesz teraz używać własnych funkcji natywnych Swift.

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

Możesz użyć random(in:) aby uzyskać losowe wartości również dla innych pierwotnych wartości; takie jak Int, Double, Float, a nawet Bool.

Szybkie wersje <4.2

Ta metoda wygeneruje losową Intwartość między podanym minimum a maksimum

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

61

Użyłem tego kodu:

var k: Int = random() % 10;

20
najpierw musisz wywołać srandom (UInt32 (czas (zero))), w przeciwnym razie zawsze zwróci tę samą sekwencję numerów
Hola Soy Edu Feliz Navidad

3
Przeczytałem dokument Apple na random () dwa razy, ale nie mogłem zebrać informacji o jego użyciu ... Chciałbym, żeby po prostu zawarli taką próbkę kodu jak powyżej. „Funkcja random () korzysta z nieliniowego, addytywnego generatora sprzężenia zwrotnego, liczb losowych, wykorzystując domyślną tabelę liczb całkowitych długich 31. Zwraca kolejne liczby pseudolosowe w zakresie od 0 do (2 31) -1. okres tego generatora liczb losowych jest bardzo duży, około 16 * ((2 31) -1). ” ... Wielkie dzięki, jabłko ... Na pewno powiem o tym w następnej pracy magisterskiej.
nocarrier

1
random () czasami prowadzi do nagłej awarii iPadów. Jeśli tak się stanie, użyj arc4random_uniform (6) z góry. Jeśli użyjesz random (), możesz utworzyć więcej losowych wartości, poprzedzając srandomdev ().
JackPearse

1
Dostałem komunikat o błędzie kompilatora:random is unavailable in Swift: Use arc4random instead.
Mike Keskinov

1
To rozwiązanie ma tendencję do modulo: zuttobenkyou.wordpress.com/2012/10/18/…
rgov

33

Począwszy od iOS 9, możesz używać nowych klas GameplayKit do generowania liczb losowych na różne sposoby.

Masz do wyboru cztery typy źródeł: ogólne losowe źródło (bez nazwy, aż do systemu, który wybiera, co robi), liniowy congruential, ARC4 i Mersenne Twister. Mogą generować losowe liczby całkowite, zmiennoprzecinkowe i boole.

Na najprostszym poziomie możesz wygenerować losową liczbę z wbudowanego losowego źródła systemu, jak to:

GKRandomSource.sharedRandom().nextInt()

To generuje liczbę między -2 147 483 648 a 2 147 483 647. Jeśli chcesz liczbę z zakresu od 0 do górnej granicy (wyłącznie), użyj tego:

GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

GameplayKit ma wbudowane kilka wygodnych konstruktorów do pracy z kostkami. Na przykład możesz rzucić sześciościenną kostką w następujący sposób:

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

Ponadto możesz kształtować losowy rozkład, używając rzeczy takich jak GKShuffledDistribution. To wymaga trochę więcej wyjaśnienia, ale jeśli jesteś zainteresowany, możesz przeczytać mój poradnik na temat losowych liczb GameplayKit .


1
Dzięki za tę wskazówkę, jest to jedna z najlepszych odpowiedzi. Aby korzystać z tych funkcji, należy dodać import GameplayKit. Swift 3 zmienił składnię naGKRandomSource.sharedRandom().nextInt(upperBound: 6)
petrsyn

7
jak ciężki jest ten zestaw do zaimportowania? nie chcę nadęty mój kod.
μολὼν.λαβέ

25

Możesz to zrobić w taki sam sposób, jak w C:

let randomNumber = arc4random()

randomNumberjest wywnioskowane, że jest typu UInt32(32-bitowa liczba całkowita bez znaku)


12
Uzupełnienie: rand, arc4random, drand48i przyjaciele są w Darwinmodule. Jest już zaimportowany, jeśli budujesz aplikację Cocoa, UIKit lub Foundation, ale musisz to zrobić import Darwinna placach zabaw.
rickster

5
I nie próbuj rzutować wyniku arc4random () na Int - to będzie działać dobrze na platformie 64-bitowej, ale na platformie 32-bitowej Ints są 32-bitowe ze znakiem, więc otrzymasz nieoczekiwany negatywny liczby. To potknęło już kilka osób, więc pomyślałem, że wspomnę o tym tutaj.
Matt Gibson,

23

Posługiwać się arc4random_uniform()

Stosowanie:

arc4random_uniform(someNumber: UInt32) -> UInt32

Daje to losowe liczby całkowite z zakresu 0do someNumber - 1.

Maksymalna wartość UInt32wynosi 4 294 967 295 (to znaczy, 2^32 - 1).

Przykłady:

  • Rzut monetą

    let flip = arc4random_uniform(2) // 0 or 1
  • Rzut kostką

    let roll = arc4random_uniform(6) + 1 // 1...6
  • Losowy dzień w październiku

    let day = arc4random_uniform(31) + 1 // 1...31
  • Losowy rok w latach 90

    let year = 1990 + arc4random_uniform(10)

Ogólna forma:

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

gdzie number, maxi minUInt32.

Co powiesz na...

arc4random ()

Możesz także uzyskać losową liczbę, używając arc4random(), co daje UInt32od 0 do 2 ^ 32-1. Tak więc, aby uzyskać losową liczbę między 0i x-1, możesz ją podzielić przez xi wziąć resztę. Innymi słowy, użyj Remainder Operator (%) :

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

Powoduje to jednak nieznaczne odchylenie modulo (patrz także tutaj i tutaj ), dlatego arc4random_uniform()jest zalecane.

Konwersja do i z Int

Zwykle dobrze byłoby zrobić coś takiego, aby przekonwertować między Inti UInt32:

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

Problem polega jednak na tym, że Intma on zasięg w -2,147,483,648...2,147,483,647systemach 32-bitowych i zakres w -9,223,372,036,854,775,808...9,223,372,036,854,775,807systemach 64-bitowych. Porównaj to z UInt32zakresem 0...4,294,967,295. UZ UInt32pomocą unsigned .

Rozważ następujące błędy:

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

Musisz tylko upewnić się, że parametry wejściowe mieszczą się w UInt32zakresie i że nie potrzebujesz również wyjścia, które jest poza tym zakresem.


19

Przykład losowej liczby między 10 (0-9);

import UIKit

let randomNumber = Int(arc4random_uniform(10))

Bardzo łatwy kod - prosty i krótki.


16

Byłem w stanie po prostu użyć rand()losowego CInt. Możesz zrobić z tego Int, używając czegoś takiego:

let myVar: Int = Int(rand())

Możesz użyć swojej ulubionej funkcji losowej C. W razie potrzeby wystarczy przekonwertować wartość na Int.


Tak, konwersja typów może być trudną sprawą, w przeciwnym razie pozwolenie konstruktorowi Int na radzenie sobie z tym jest prawdziwym oszczędzaniem bólu.
Kzrbill

4
Zauważ, że jeśli nie wywołujesz srand (...) (wywołaj go tylko raz) przed użyciem rand (), sekwencja liczb zawsze będzie dokładnie taka sama między każdym uruchomieniem twojego programu. Jeśli nie chcesz tego, użyj arc4random ()
SomeGuy

2
Możesz również użyć random(), który zwraca Intraczej niż UInt32- i jak wspomniano @SomeGuy, po prostu zadzwoń srandom(arc4random())raz w dowolnym miejscu przed użyciem, aby upewnić się, że ma on inne, losowe źródło dla każdego wykonania twojego programu.
brittlewis12

1
Czy ktoś może komentować rand () vs arc4random_uniform ()?
Ruben Martinez Jr.

16

Odpowiedź @ jstn jest dobra, ale nieco gadatliwa. Swift jest znany jako język zorientowany na protokół, dzięki czemu możemy osiągnąć ten sam wynik bez konieczności implementowania kodu typu Booster dla każdej klasy w rodzinie liczb całkowitych, dodając domyślną implementację rozszerzenia protokołu.

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

Teraz możemy zrobić:

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

i wszystkie inne klasy całkowite są w porządku.


11

W Swift 4.2 możesz generować losowe liczby, wywołując random()metodę na dowolnym typie liczbowym, podając zakres, z którym chcesz pracować. Na przykład generuje losową liczbę z zakresu od 1 do 9, włącznie po obu stronach

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

Również z innymi typami

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

9

Oto biblioteka, która dobrze wykonuje to zadanie 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

Chciałbym dodać do istniejących odpowiedzi, że przykład generatora liczb losowych w książce Swift to Generator liniowej zbieżności (LCG), jest on mocno ograniczony i nie powinien być wyjątkiem trywialnych przykładów, w których jakość losowości nie to nie ma znaczenia. I LCG nigdy nie powinien być używany do celów kryptograficznych .

arc4random()jest znacznie lepszy i może być używany do większości celów, ale ponownie nie powinien być wykorzystywany do celów kryptograficznych.

Jeśli chcesz mieć coś, co gwarantuje bezpieczeństwo kryptograficzne, użyj SecCopyRandomBytes(). Zauważ, że jeśli w coś wbudujesz generator liczb losowych, ktoś inny może (nie) użyć go do celów kryptograficznych (takich jak generowanie hasła, klucza lub soli), powinieneś rozważyć użycie go SecCopyRandomBytes(), nawet jeśli twoja potrzeba tego nie robi. całkiem tego wymaga.


6

Od wersji Swift 4.2

Istnieje nowy zestaw interfejsów API:

let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomDouble = Double.random(in: 1 ... 10)
  • Wszystkie typy numeryczne mają teraz wybraną random(in:)metodę range.

  • Zwraca liczbę równomiernie rozmieszczoną w tym zakresie.


TL; DR

Cóż jest nie tak z „dobrym” starym sposobem?

  1. Musisz użyć importowanych interfejsów API C (różnią się one między platformami) .

  2. A ponadto ...

Co jeśli powiem ci, że los nie jest taki losowy?

Jeśli używasz arc4random() (aby obliczyć resztę) jak arc4random() % aNumber, wynik nie jest równomiernie rozłożone pomiędzy 0i aNumber. Istnieje problem zwany stronniczością Modulo .

Odchylenie modulo

Zwykle funkcja generuje losową liczbę między 0i MAX (zależy od typu itp . ) . Aby zrobić szybki, łatwy przykład, załóżmy, że maksymalna liczba to 7i zależy Ci na losowej liczbie w zakresie 0 ..< 2 (lub odstępie [0, 3), jeśli wolisz) .

Te prawdopodobieństwa dla poszczególnych numerów są:

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

Innymi słowy, bardziej prawdopodobne jest, że skończysz z 0 lub 1 niż 2 . Oczywiście należy pamiętać, że jest to bardzo uproszczone, a liczba MAX jest znacznie wyższa, dzięki czemu jest bardziej „sprawiedliwa”.

Ten problem rozwiązano w SE-0202 - Losowe zjednoczenie w Swift 4.2


5

Bez arc4Random_uniform () w niektórych wersjach Xcode (w 7.1 działa, ale nie wykonuje autouzupełniania). Możesz to zrobić zamiast tego.

Aby wygenerować losową liczbę od 0-5. Pierwszy

import GameplayKit

Następnie

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

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

Tutaj 5 upewni się, że liczba losowa zostanie wygenerowana od zera do czterech. Możesz odpowiednio ustawić wartość.


1
Jeśli zdasz 5, zwróci 5 możliwych wyników od zera do czterech. 0 ... 4
Leo Dabus

3

Szybki 4.2

Pa pa, aby zaimportować libellę Foundation C. 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. Używasz losowego (w :) do generowania losowych cyfr z zakresów.
  2. randomElement () zwraca zero, jeśli zakres jest pusty, więc rozpakowujesz zwróconą wartość Int? z jeśli pozwolisz.
  3. Używasz random (in :), aby wygenerować losowy Double, Float lub CGFloat, a random (), aby zwrócić losowy Bool.

Więcej @ Oficjalny


2

Poniższy kod wygeneruje bezpieczną liczbę losową z przedziału od 0 do 255:

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

Nazywasz to tak:

print(UInt8.random)

W przypadku większych liczb staje się to bardziej skomplikowane.
To najlepsze, co mogłem wymyślić:

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

W tych metodach używa się dodatkowej liczby losowej, aby określić, ile UInt8s będzie używanych do utworzenia liczby losowej. Ostatnia linia zamienia [UInt8]się UInt16lubUInt32 .

Nie wiem, czy dwa ostatnie nadal liczą się jako naprawdę losowe, ale możesz je dostosować do własnych upodobań :)


Sprytnie uniknąłeś uprzedzeń wprowadzonych przez modulo, for1 za to. Możesz ostrzec czytelników, dlaczego to zrobiłeś.
jww

To ciekawe, tak naprawdę nie sądziłem, że może tu występować błąd modulo. Być może szanse na uzyskanie małej liczby nie są takie same, jak uzyskanie dużej liczby.
Zyphrax,

2

Szybki 4.2

Swift 4.2 zawiera natywny i dość w pełni funkcjonalny interfejs API liczb losowych w standardowej bibliotece. ( Propozycja Swift Evolution SE-0202 )

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

Wszystkie typy liczb mają statyczne losowe (w :), które przyjmuje zakres i zwraca liczbę losową z podanego zakresu


1

Swift 4.2, Xcode 10.1 .

W systemach iOS, macOS i tvOS można używać losowego źródła systemowego w środowisku Xcode GameKit. Tutaj możesz znaleźć GKRandomSourceklasę za pomocą jej sharedRandom()metody klasowej:

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

Lub po prostu użyj randomElement()metody, która zwraca losowy element kolekcji:

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

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

0

Możesz użyć w GeneratorOften sposób:

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
Jak losowo Fibonacciego?
Nikolai Ruhe

Cześć Nikołaj, Ten blok kodu to stara wersja Swift 1.2. Jeśli wypróbujesz nową wersję Swift 2.0. To nie byłaby praca.
Durul Dalkanat

2
Rozumiem, ale nadal wygląda mi na generator generatora Fibonacciego, a nie na liczby losowe, o które pytano w pytaniu.
Nikolai Ruhe,

0

Używam tego kodu, aby wygenerować losową liczbę:

//
//  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
Witamy w SO. Odradzane są tylko odpowiedzi na kod - edytuj swoją odpowiedź, aby wyjaśnić, dlaczego ten kod odpowiada na pytanie i jak działa. Aby uzyskać więcej informacji, zobacz stackoverflow.com/help/how-to-answer.
Tim Malone

2
Podaj kontekst wokół swojej odpowiedzi i witaj w Stackoverflow. :)
Jonathan Eustace

0

Detale

xCode 9.1, Swift 4

Rozwiązanie zorientowane matematycznie (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
}

Zastosowanie rozwiązania (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]

Rozwiązanie zorientowane na programistów (2)

Nie zapomnij dodać tutaj kodu rozwiązania zorientowanego na matematykę (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]
    }
}

Zastosowanie rozwiązania (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]

Pełna próbka

Nie zapomnij dodać tutaj kodów rozwiązania (1) i rozwiązania (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]
}

Przykładowy wynik

wprowadź opis zdjęcia tutaj


2
Ta odpowiedź jest nie na temat. Pytanie brzmiało, jak wygenerować liczbę losową. Nie jak zrobić bibliotekę liczb losowych. Do licha.
Andrew Paul Simmons
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.