Menghasilkan nomor acak dengan Swift


92

Saya perlu membuat nomor acak.

Tampaknya arc4randomfungsi tersebut sudah tidak ada lagi seperti halnya arc4random_uniformfungsinya.

Pilihan yang saya miliki adalah arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int), dan arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).

Saya tidak dapat menemukan dokumen apa pun tentang fungsinya dan tidak ada komentar di file header yang memberi petunjuk.


3
Tampaknya pelengkapan otomatis di Xcode baru saja rusak. Saya berani bersumpah saya mengetiknya tanpa pelengkapan otomatis dan tidak dapat dikompilasi. Bekerja sekarang. Referensi bagus oleh @arsen
Big_Mac

1
arc4random_uniform tersedia. Ini adalah bagian dari Foundation API bukan bagian asli dari bahasa tersebut, jadi Anda memerlukan "import Foundation" (atau "import UIKit") di bagian atas file untuk membuatnya tersedia.
Vince O'Sullivan

probabilitas = Int (arc4random_uniform (UInt32 (total))) - karena typeahead rusak, keluhan pengetikan tidak spesifik, itu keluhan casting saya berasal dari dua kesalahan yang berbeda
bshirley

Jawaban:


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

Di bawah tenda yang digunakan Swift arc4random_bufuntuk menyelesaikan pekerjaan.

===== Cepat 4.1 / Xcode 9 =====

arc4random()mengembalikan nomor acak dalam kisaran 0 hingga 4294967 295

drand48()mengembalikan nomor acak dalam kisaran 0,0 hingga 1,0

arc4random_uniform(N)mengembalikan nomor acak dalam rentang 0 hingga N - 1

Contoh:

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 () direkomendasikan untuk konstruksi seperti arc4random() % upper_boundkarena menghindari "bias modulo" saat batas atas bukan pangkat dua.


Float.random()saat ini ditandai Beta , dan karenanya memberi'Float' has no member 'random'
Dale

22

Anda juga bisa mencoba:

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

Saya harus menambahkan "UInt32" untuk membuatnya bekerja.


1
Ketika saya mencari fungsi ini, saya melihat public func arc4random_uniform(_: UInt32) -> UInt32. Jadi saya bertanya-tanya mengapa mengonversi ke parameter ke UInt32? Apakah ada hal lain yang terjadi di sini?
Mark Moeykens

8

Panggil saja fungsi ini dan berikan kisaran nomor minimum dan maksimum dan Anda akan mendapatkan nomor acak.

Misalnya seperti randomNumber (MIN: 0, MAX: 10) dan Anda akan mendapatkan nomor antara 0 sampai 9 .

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

Catatan: - Anda akan selalu mendapatkan keluaran berupa nomor Integer.


1
Saya pikir perlu: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

Setelah beberapa penyelidikan saya menulis ini:

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

Sekarang tinggal Math.randomFraction()ambil bilangan random [0..1 [tanpa harus ingat seeding dulu. Semoga ini membantu seseorang: o)


4

Perbarui dengan 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

Pilihan lainnya adalah dengan menggunakan algoritma 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
}

Algoritme ini memiliki periode 2 ^ 128 - 1 dan lolos semua pengujian rangkaian pengujian BigCrush . Perhatikan bahwa meskipun ini adalah penghasil nomor acak semu berkualitas tinggi dengan periode yang lama, ini bukan penghasil nomor acak yang aman secara kriptografis .

Anda dapat menyemainya dari waktu saat ini atau sumber entropi acak lainnya. Misalnya, jika Anda memiliki fungsi bernama urand64()read a UInt64from /dev/urandom, Anda dapat menggunakannya seperti ini:

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

Mengapa Anda tidak memberikan penjelasan untuk kode ini?
direformasi

1

Di Swift 3:

Ini akan menghasilkan nomor acak antara 0 hingga batas

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

dan jika saya ingin menghasilkan nomor acak dari 5 hingga 10, bukan dari 0 hingga n nomor
Rishi

1
@Rishi Dari 5 hingga 10 akanarc4random_uniform(6) + 5
Matt Le Fleur

1

Implementasi saya sebagai ekstensi Int. Akan menghasilkan angka acak dalam jangkauanfrom..<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

Ini adalah bagaimana saya mendapatkan nomor acak antara 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)))]
}

pemakaian:

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

1

Pilihan lainnya adalah menggunakan GKMersenneTwisterRandomSource dari GameKit. Dokumen tersebut mengatakan:

Sumber acak semu deterministik yang menghasilkan bilangan acak berdasarkan algoritme twister mersenne. Ini adalah sumber acak deterministik yang cocok untuk membuat mekanisme permainan yang andal. Ini sedikit lebih lambat dari sumber Arc4, tetapi lebih acak, karena memiliki periode yang lebih lama hingga urutan berulang. Meskipun bersifat deterministik, ini bukanlah sumber acak kriptografi. Namun itu cocok untuk kebingungan data permainan.

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)

Contoh diambil dari kode sampel Apple: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift


1

Saya terlambat ke pesta 🤩🎉

Menggunakan fungsi yang memungkinkan Anda mengubah ukuran larik dan pemilihan rentang dengan cepat adalah metode yang paling serbaguna. Anda juga bisa menggunakan peta sehingga sangat ringkas. Saya menggunakannya di semua pengujian kinerja / benchmarking saya.

elementsadalah jumlah item dalam larik yang
hanya menyertakan angka dari0...max

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

Code Sense / Placeholder terlihat seperti ini. randArr(elements: Int, max: Int)

10 elemen dalam array saya mulai dari 0 hingga 1000.

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

0

Anda dapat menggunakan ini dalam tarif tertentu:

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

Lets Code dengan Swift untuk nomor acak atau string acak :)

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

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

itu akan memberi Anda keluaran secara acak.


0

Jangan lupa bahwa beberapa angka akan berulang! jadi Anda perlu melakukan sesuatu seperti ....

totalQuestions saya adalah 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

lihat, saya punya masalah yang sama tetapi saya memasukkan fungsi sebagai variabel global

sebagai

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

func GetCase(){

your code
}

jelas ini tidak efektif, jadi saya hanya menyalin dan menempelkan kode ke dalam fungsi sehingga dapat digunakan kembali, lalu xcode menyarankan saya untuk mengatur var sebagai konstan sehingga kode saya

func GetCase() {

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

   if categoria == 1 {
    }
}

itu adalah bagian dari kode saya jadi xcode memberi tahu saya sesuatu yang tidak dapat diubah dan inisialisasi tetapi, itu tetap membangun aplikasi dan saran itu hilang begitu saja

semoga membantu

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.