Tạo số ngẫu nhiên với Swift


92

Tôi cần tạo một số ngẫu nhiên.

Nó xuất hiện arc4randomchức năng không còn tồn tại cũng như arc4random_uniformchức năng.

Các tùy chọn tôi có được arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int)arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).

Tôi không thể tìm thấy bất kỳ tài liệu nào về các chức năng và không có nhận xét nào trong tệp tiêu đề đưa ra gợi ý.


3
Có vẻ như tính năng tự động hoàn thành trong Xcode vừa bị phá vỡ. Tôi có thể thề rằng tôi đã nhập nó mà không có tính năng tự động hoàn thành và nó không biên dịch. Đang làm việc. Thoải mái tham khảo @arsen
Big_Mac

1
arc4random_uniform có sẵn. Nó là một phần của Foundation API không phải là một phần bản địa của ngôn ngữ, vì vậy bạn cần một "import Foundation" (hoặc "import UIKit") ở đầu tệp để cung cấp nó.
Vince O'Sullivan

Xác suất = Int (arc4random_uniform (UInt32 (tổng cộng))) - bởi vì typeahead bị hỏng, các khiếu nại gõ được không rõ ràng, đã được đơn khiếu nại của tôi đúc đến từ hai lỗi khác nhau
bshirley

Câu trả lời:


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

Swift sử dụng arc4random_bufđể hoàn thành công việc.

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

arc4random()trả về một số ngẫu nhiên trong phạm vi từ 0 đến 4 294 967 295

drand48()trả về một số ngẫu nhiên trong phạm vi từ 0,0 đến 1,0

arc4random_uniform(N)trả về một số ngẫu nhiên trong phạm vi từ 0 đến N - 1

Ví dụ:

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 () được đề xuất trên các cấu trúc như arc4random() % upper_boundnó tránh "thiên vị modulo" khi giới hạn trên không phải là lũy thừa của hai.


Float.random()hiện đang được đánh dấu là Beta và vì vậy sẽ cho'Float' has no member 'random'
Dale

22

Bạn cũng có thể thử:

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

Tôi đã phải thêm "UInt32" để làm cho nó hoạt động.


1
Khi tôi tra cứu chức năng này, tôi thấy public func arc4random_uniform(_: UInt32) -> UInt32. Vì vậy, tôi tự hỏi tại sao chuyển đổi thành tham số thành UInt32? Có điều gì khác đang xảy ra ở đây?
Mark Moeykens

8

Chỉ cần gọi hàm này và cung cấp dải số tối thiểu và tối đa và bạn sẽ nhận được một số ngẫu nhiên.

ví dụ như randomNumber (MIN: 0, MAX: 10) và Bạn sẽ nhận được số từ 0 đến 9 .

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

Lưu ý: - Bạn sẽ luôn nhận được đầu ra một số Nguyên.


1
Tôi nghĩ rằng cần phải: func randomNumber(MIN: Int, MAX: Int)-> Int{ return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN)); }
Adahus

5

Sau một số cuộc điều tra, tôi đã viết điều này:

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

Bây giờ bạn chỉ có thể làm Math.randomFraction()để nhận các số ngẫu nhiên [0..1 [mà không cần phải nhớ gieo hạt trước. Hy vọng điều này sẽ giúp ai đó: o)


4

Cập nhật với nhanh chóng 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

Một tùy chọn khác là sử dụng thuật toán 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
}

Thuật toán này có khoảng thời gian là 2 ^ 128 - 1 và vượt qua tất cả các bài kiểm tra của bộ kiểm tra BigCrush . Lưu ý rằng mặc dù đây là trình tạo số giả ngẫu nhiên chất lượng cao với thời gian dài, nhưng nó không phải là trình tạo số ngẫu nhiên an toàn bằng mật mã .

Bạn có thể gieo nó từ thời điểm hiện tại hoặc bất kỳ nguồn entropy ngẫu nhiên nào khác. Ví dụ: nếu bạn có một hàm được gọi là urand64()đọc UInt64từ /dev/urandom, bạn có thể sử dụng nó như sau:

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

Tại sao bạn không cung cấp lời giải thích cho mã này?
cải cách

1

Trong Swift 3:

Nó sẽ tạo ra số ngẫu nhiên giữa 0 để giới hạn

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

và nếu tôi muốn tạo ra một số ngẫu nhiên từ 5 đến 10, không phải từ 0 đến số n
Rishi

1
@Rishi Từ 5 đến 10 sẽ làarc4random_uniform(6) + 5
Matt Le Fleur

1

Việc triển khai của tôi dưới dạng phần mở rộng Int. Sẽ tạo ra các số ngẫu nhiên trong phạm vifrom..<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

Đây là cách tôi lấy một số ngẫu nhiên giữa 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)))]
}

sử dụng:

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

1

Một tùy chọn khác là sử dụng GKMersenneTwisterRandomSource từ GameKit. Các tài liệu nói:

Một nguồn giả ngẫu nhiên xác định tạo ra các số ngẫu nhiên dựa trên thuật toán xoắn mersenne. Đây là nguồn ngẫu nhiên xác định phù hợp để tạo cơ chế chơi đáng tin cậy. Nó chậm hơn một chút so với nguồn Arc4, nhưng ngẫu nhiên hơn, ở chỗ nó có khoảng thời gian dài hơn cho đến khi các chuỗi lặp lại. Trong khi xác định, đây không phải là một nguồn ngẫu nhiên mật mã. Tuy nhiên, nó phù hợp để làm xáo trộn dữ liệu trò chơi.

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)

Ví dụ được lấy từ mã mẫu của Apple: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPworthy/RandomNumberGeneratorHelper.swift


1

Tôi đến muộn bữa tiệc 🤩🎉

Sử dụng một hàm cho phép bạn thay đổi kích thước của mảng và lựa chọn phạm vi nhanh chóng là phương pháp linh hoạt nhất. Bạn cũng có thể sử dụng bản đồ để nó rất ngắn gọn. Tôi sử dụng nó trong tất cả các bài kiểm tra hiệu suất / chấm điểm trên băng ghế dự bị.

elementslà số mục trong mảng
chỉ bao gồm các số từ0...max

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

Code Sense / Trình giữ chỗ trông như thế này. randArr(elements: Int, max: Int)

10 phần tử trong mảng của tôi từ 0 đến 1000.

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

0

bạn có thể sử dụng điều này với tỷ lệ cụ thể:

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

Cho phép viết mã bằng Swift cho số ngẫu nhiên hoặc chuỗi ngẫu nhiên :)

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

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

nó sẽ cung cấp cho bạn đầu ra một cách ngẫu nhiên.


0

Đừng quên rằng một số con số sẽ lặp lại! vì vậy bạn cần phải làm một cái gì đó như ...

tổng số câu hỏi của tôi là 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

nhìn này, tôi gặp vấn đề tương tự nhưng tôi chèn hàm dưới dạng một biến toàn cục

như

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

func GetCase(){

your code
}

rõ ràng điều này không hiệu quả, vì vậy tôi chỉ cần sao chép và dán mã vào hàm để nó có thể được sử dụng lại, sau đó xcode đề nghị tôi đặt var là hằng số để mã của tôi là

func GetCase() {

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

   if categoria == 1 {
    }
}

Đó là một phần mã của tôi, vì vậy xcode cho tôi biết điều gì đó về khả năng khởi tạo và inmutable, nhưng, nó vẫn xây dựng ứng dụng và lời khuyên đó chỉ đơn giản là giải thích

hy vọng nó giúp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.