Zufallszahlen mit Swift generieren


92

Ich muss eine Zufallszahl generieren.

Es scheint, dass die arc4randomFunktion nicht mehr existiert, ebenso wie die arc4random_uniformFunktion.

Die Optionen , die wir haben sind arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int)und arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).

Ich kann keine Dokumente zu den Funktionen finden und keine Kommentare in den Header-Dateien geben Hinweise.


3
Es scheint, dass die automatische Vervollständigung in Xcode gerade kaputt war. Ich hätte schwören können, dass ich es ohne automatische Vervollständigung eingegeben habe und es nicht kompiliert wurde. Arbeite jetzt. Schöne Referenz von @arsen
Big_Mac

1
arc4random_uniform ist verfügbar. Es ist Teil der Foundation-API und kein nativer Teil der Sprache. Daher benötigen Sie am Anfang der Datei eine "Foundation importieren" (oder "UIKit importieren"), um sie verfügbar zu machen.
Vince O'Sullivan

Wahrscheinlichkeit = Int (arc4random_uniform (UInt32 (total))) - da der Typkopf defekt ist, waren die Schreibbeschwerden unspezifisch, das war meine Casting-Beschwerde, die von zwei verschiedenen Fehlern kam
bshirley

Antworten:


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

Unter der Haube arc4random_buferledigt Swift seine Arbeit.

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

arc4random()Gibt eine Zufallszahl im Bereich von 0 bis 4 zurück. 294 967 295

drand48()gibt eine Zufallszahl im Bereich von 0,0 bis 1,0 zurück

arc4random_uniform(N)gibt eine Zufallszahl im Bereich von 0 bis N - 1 zurück

Beispiele:

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 () wird gegenüber Konstruktionen empfohlen, arc4random() % upper_boundda es "Modulo Bias" vermeidet, wenn die Obergrenze keine Zweierpotenz ist.


Float.random()ist derzeit als Beta markiert und gibt so'Float' has no member 'random'
Dale

22

Sie könnten auch versuchen:

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

Ich musste "UInt32" hinzufügen, damit es funktioniert.


1
Wenn ich diese Funktion nachschlage, sehe ich public func arc4random_uniform(_: UInt32) -> UInt32. Ich frage mich also, warum ich in den Parameter konvertiere UInt32? Passiert hier noch etwas?
Mark Moeykens

8

Rufen Sie einfach diese Funktion auf und geben Sie den minimalen und maximalen Zahlenbereich an. Sie erhalten eine Zufallszahl.

zB wie randomNumber (MIN: 0, MAX: 10) und Sie erhalten eine Zahl zwischen 0 und 9 .

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

Hinweis: - Sie erhalten immer eine Ganzzahl.


1
Ich denke muss sein: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

Nach einigen Nachforschungen schrieb ich Folgendes:

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

Jetzt können Sie nur Math.randomFraction()noch Zufallszahlen [0..1 [erhalten, ohne sich zuerst an das Seeding erinnern zu müssen. Hoffe das hilft jemandem: o)


4

Update mit 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

Eine weitere Option ist die Verwendung des xorshift128plus- Algorithmus:

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
}

Dieser Algorithmus hat eine Periode von 2 ^ 128 - 1 und besteht alle Tests der BigCrush -Testsuite. Beachten Sie, dass dies zwar ein qualitativ hochwertiger Pseudozufallszahlengenerator mit langer Laufzeit ist, jedoch kein kryptografisch sicherer Zufallszahlengenerator .

Sie könnten es aus der aktuellen Zeit oder einer anderen zufälligen Entropiequelle aussäen. Wenn Sie beispielsweise eine Funktion mit dem Namen urand64()a UInt64from haben /dev/urandom, können Sie diese folgendermaßen verwenden:

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

Warum erklären Sie diesen Code nicht?
Reformiert

1

In Swift 3:

Es wird eine Zufallszahl zwischen 0 und 0 generiert

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

und wenn ich eine Zufallszahl von 5 bis 10 erzeugen möchte, nicht von 0 bis n
Rishi

1
@ Rishi Von 5 bis 10 wärearc4random_uniform(6) + 5
Matt Le Fleur

1

Meine Implementierung als Int-Erweiterung. Erzeugt Zufallszahlen im Bereichfrom..<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

So bekomme ich eine Zufallszahl zwischen 2 Ints!

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

Verwendung:

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

1

Eine weitere Option ist die Verwendung von GKMersenneTwisterRandomSource von GameKit. Die Dokumente sagen:

Eine deterministische Pseudozufallsquelle, die Zufallszahlen basierend auf einem Mersenne-Twister-Algorithmus generiert. Dies ist eine deterministische Zufallsquelle, die zur Erstellung zuverlässiger Spielmechaniken geeignet ist. Es ist etwas langsamer als eine Arc4-Quelle, aber zufälliger, da es einen längeren Zeitraum bis zur Wiederholung von Sequenzen hat. Dies ist zwar deterministisch, aber keine kryptografische Zufallsquelle. Es ist jedoch zur Verschleierung von Spieldaten geeignet.

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)

Beispiel aus Apples Beispielcode: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1

Ich bin zu spät zur Party 🤩🎉

Die vielseitigste Methode ist die Verwendung einer Funktion, mit der Sie die Größe des Arrays und die Bereichsauswahl im laufenden Betrieb ändern können. Sie können auch eine Karte verwenden, damit diese sehr übersichtlich ist. Ich benutze es in all meinen Leistungstests / Benchmarking.

elementsist die Anzahl der Elemente im Array
, einschließlich der Nummern von0...max

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

Code Sense / Platzhalter sehen so aus. randArr(elements: Int, max: Int)

10 Elemente in meinem Array von 0 bis 1000.

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

0

Sie können dies in einer bestimmten Rate verwenden:

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

Lässt Code mit Swift für die Zufallszahl oder Zufallszeichenfolge :)

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

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

Sie erhalten eine zufällige Ausgabe.


0

Vergessen Sie nicht, dass sich einige Zahlen wiederholen! Sie müssen also so etwas wie ...

Meine Gesamtzahl der Fragen war 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

schau, ich hatte das gleiche Problem, aber ich füge die Funktion als globale Variable ein

wie

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

func GetCase(){

your code
}

Offensichtlich ist dies nicht effizient, also kopiere ich einfach den Code und füge ihn in die Funktion ein, damit er wiederverwendbar ist. Dann schlägt mir xcode vor, die Variable so konstant wie meinen Code zu setzen

func GetCase() {

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

   if categoria == 1 {
    }
}

Nun, das ist ein Teil meines Codes, also sagt mir xcode etwas von unveränderlich und initialisiert, aber es baut die App trotzdem auf und dieser Rat verschwindet einfach

ich hoffe es hilft

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.