How does one generate a random number in Apple's Swift language?

后端 未结 25 1563
有刺的猬
有刺的猬 2020-11-22 09:51

I realize the Swift book provided an implementation of a random number generator. Is the best practice to copy and paste this implementation in one\'s own program? Or is t

相关标签:
25条回答
  • 2020-11-22 10:28

    @jstn's answer is good, but a bit verbose. Swift is known as a protocol-oriented language, so we can achieve the same result without having to implement boilerplate code for every class in the integer family, by adding a default implementation for the protocol extension.

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

    Now we can do:

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

    and all other integer classes are ok.

    0 讨论(0)
  • 2020-11-22 10:28

    Here is a library that does the job well 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
        }
    }
    
    0 讨论(0)
  • 2020-11-22 10:30

    As of iOS 9, you can use the new GameplayKit classes to generate random numbers in a variety of ways.

    You have four source types to choose from: a general random source (unnamed, down to the system to choose what it does), linear congruential, ARC4 and Mersenne Twister. These can generate random ints, floats and bools.

    At the simplest level, you can generate a random number from the system's built-in random source like this:

    GKRandomSource.sharedRandom().nextInt()
    

    That generates a number between -2,147,483,648 and 2,147,483,647. If you want a number between 0 and an upper bound (exclusive) you'd use this:

    GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
    

    GameplayKit has some convenience constructors built in to work with dice. For example, you can roll a six-sided die like this:

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

    Plus you can shape the random distribution by using things like GKShuffledDistribution. That takes a little more explaining, but if you're interested you can read my tutorial on GameplayKit random numbers.

    0 讨论(0)
  • 2020-11-22 10:30

    Swift 4.2

    Bye bye to import Foundation C lib 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. You use random(in:) to generate random digits from ranges.
    2. randomElement() returns nil if the range is empty, so you unwrap the returned Int? with if let.
    3. You use random(in:) to generate a random Double, Float or CGFloat and random() to return a random Bool.

    More @ Official

    0 讨论(0)
  • 2020-11-22 10:31

    Swift 4.2+

    Swift 4.2 shipped with Xcode 10 introduces new easy-to-use random functions for many data types. You can call the random() method on numeric types.

    let randomInt = Int.random(in: 0..<6)
    let randomDouble = Double.random(in: 2.71828...3.14159)
    let randomBool = Bool.random()
    
    0 讨论(0)
  • 2020-11-22 10:32

    Updated: August 06, 2020.

    Swift 5.3

    Let's assume we have an array:

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


    For iOS and macOS you can use system-wide random source in Xcode's framework GameKit. Here you can find GKRandomSource class with its sharedRandom() class method:

    import GameKit
    
    private func randomNumberGenerator() -> Int {
        let random = GKRandomSource.sharedRandom().nextInt(upperBound: numbers.count)
        return numbers[random]
    }
    
    randomNumberGenerator()
    


    Also you can use a randomElement() method that returns a random element of a collection:

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


    Or use arc4random_uniform(). Pay attention that this method returns UInt32.

    let generator = Int(arc4random_uniform(10))
    print(generator)
    


    And, of course, we can use a makeIterator() method that returns an iterator over the elements of the collection.

    let iterator: Int = (1...10).makeIterator().shuffled().first!
    print(iterator)
    


    The final example you see here returns a random value within the specified range with a help of static func random(in range: ClosedRange<Int>) -> Int.

    let randomizer = Int.random(in: 1...10)
    print(randomizer)
    
    0 讨论(0)
提交回复
热议问题