Generowanie liczb losowych za pomocą Swift


92

Muszę wygenerować liczbę losową.

Wygląda na to, że arc4randomfunkcja już nie istnieje, podobnie jak arc4random_uniformfunkcja.

Dostępne opcje to mam arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int)i arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).

Nie mogę znaleźć żadnych dokumentów dotyczących funkcji, a żadne komentarze w plikach nagłówkowych nie dają wskazówek.


3
Wydawałoby się, że autouzupełnianie w Xcode właśnie się zepsuło. Mógłbym przysiąc, że wpisałem go bez autouzupełniania i nie skompilowałem. Teraz pracuje. Niezłe odniesienie autorstwa @arsen
Big_Mac,

1
arc4random_uniform jest dostępny. Jest to część API Foundation, a nie natywna część języka, więc aby udostępnić plik, na początku pliku należy umieścić element „Import Foundation” (lub „UIKit importu”).
Vince O'Sullivan

prawdopodobieństwo = Int (arc4random_uniform (UInt32 (total))) - ponieważ typahead jest zepsuty, skargi dotyczące pisania były niespecyficzne, to była moja skarga do castingu pochodząca z dwóch różnych błędów
bshirley

Odpowiedzi:


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

Pod maską Swift wykorzystuje arc4random_bufdo wykonania pracy.

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

arc4random()zwraca liczbę losową z zakresu od 0 do 4 294 967 295

drand48()zwraca liczbę losową z zakresu od 0,0 do 1,0

arc4random_uniform(N)zwraca liczbę losową z zakresu od 0 do N - 1

Przykłady:

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

Funkcja arc4random_uniform () jest zalecana nad konstrukcjami takimi arc4random() % upper_boundjak, ponieważ pozwala uniknąć "odchylenia modulo", gdy górna granica nie jest potęgą dwójki.


Float.random()jest obecnie oznaczony jako Beta , więc daje'Float' has no member 'random'
Dale

22

Ty też możesz spróbować:

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

Musiałem dodać „UInt32”, aby działało.


1
Kiedy sprawdzam tę funkcję, widzę public func arc4random_uniform(_: UInt32) -> UInt32. Zastanawiam się więc po co konwertować na parametr na UInt32? Czy coś się tu dzieje?
Mark Moeykens

8

Po prostu wywołaj tę funkcję i podaj minimalny i maksymalny zakres liczby, a otrzymasz losową liczbę.

np. jak randomNumber (MIN: 0, MAX: 10), a otrzymasz liczbę od 0 do 9 .

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

Uwaga: - Na wyjściu zawsze otrzymasz liczbę całkowitą.


1
Myślę, że powinno być: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

Po pewnym dochodzeniu napisałem to:

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

Teraz możesz po prostu zrobić Math.randomFraction()losowe liczby [0..1 [bez konieczności wcześniejszego zapamiętywania rozstawienia. Mam nadzieję, że to komuś pomoże: o)


4

Aktualizacja za pomocą 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

Inną opcją jest użycie algorytmu 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
}

Ten algorytm ma okres 2 ^ 128 - 1 i przechodzi wszystkie testy zestawu testów BigCrush . Zauważ, że chociaż jest to wysokiej jakości generator liczb pseudolosowych z długim okresem, nie jest to generator liczb losowych zabezpieczony kryptograficznie .

Możesz wysiać ją z aktualnego czasu lub dowolnego innego losowego źródła entropii. Na przykład, jeśli masz funkcję o nazwie, urand64()która odczytuje UInt64z /dev/urandom, możesz jej użyć w następujący sposób:

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

Dlaczego nie podasz wyjaśnienia dla tego kodu?
zreformowany

1

W Swift 3:

Wygeneruje liczbę losową od 0 do ograniczenia

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

a jeśli chcę wygenerować losową liczbę od 5 do 10, a nie od 0 do n
Rishi

1
@Rishi Od 5 do 10 będziearc4random_uniform(6) + 5
Matt Le Fleur

1

Moja realizacja jako rozszerzenie Int. Wygeneruje liczby losowe w zakresiefrom..<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

W ten sposób otrzymuję liczbę losową między 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)))]
}

stosowanie:

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

1

Inną opcją jest użycie GKMersenneTwisterRandomSource z GameKit . Doktorzy mówią:

Deterministyczne źródło pseudolosowe, które generuje liczby losowe na podstawie algorytmu twistera mersenne. To deterministyczne, losowe źródło odpowiednie do stworzenia niezawodnej mechaniki rozgrywki. Jest nieco wolniejsze niż źródło Arc4, ale bardziej losowe, ponieważ ma dłuższy okres do powtórzenia sekwencji. Chociaż jest to deterministyczne, nie jest to losowe źródło kryptograficzne. Nadaje się jednak do zaciemniania danych dotyczących rozgrywki.

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)

Przykład zaczerpnięty z przykładowego kodu Apple: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1

Spóźniłem się na imprezę 🤩🎉

Najbardziej wszechstronną metodą jest użycie funkcji, która pozwala na zmianę rozmiaru tablicy i wybór zakresu w locie. Możesz także użyć mapy, więc jest bardzo zwięzła. Używam go we wszystkich moich testach wydajnościowych / benchmarkach.

elementsto liczba elementów w tablicy
zawierająca tylko liczby od0...max

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

Tak wygląda wyczucie kodu / symbole zastępcze. randArr(elements: Int, max: Int)

10 elementów w mojej tablicy od 0 do 1000.

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

0

możesz użyć tego w określonej stawce:

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

Pozwala kodować Swift dla losowej liczby lub losowego ciągu :)

let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]

      let randomNumber = arc4random_uniform(UInt32(quotes.count))
      let quoteString = quotes[Int(randomNumber)]
      print(quoteString)

da ci to wyjście losowo.


0

Nie zapominaj, że niektóre liczby będą się powtarzać! więc musisz zrobić coś takiego ...

moja suma pytań wyniosła 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

spójrz, miałem ten sam problem, ale wstawiam funkcję jako zmienną globalną

tak jak

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

func GetCase(){

your code
}

oczywiście nie jest to skuteczne, więc po prostu kopiuję i wklejam kod do funkcji, aby można go było ponownie użyć, a następnie xcode sugeruje mi ustawienie zmiennej jako stałej, aby mój kod był

func GetCase() {

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

   if categoria == 1 {
    }
}

cóż, to część mojego kodu, więc xcode mówi mi coś o niezmienności i inicjalizacji, ale i tak tworzy aplikację, a ta rada po prostu znika

mam nadzieję, że to pomoże

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.