How does one generate a random number in Apple'

2018-12-31 13:07发布

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 there a library that does this that we can use now?

标签: swift random
25条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 13:07

Use arc4random_uniform(n) for a random integer between 0 and n-1.

let diceRoll = Int(arc4random_uniform(6) + 1)

Cast the result to Int so you don't have to explicitly type your vars as UInt32 (which seems un-Swifty).

查看更多
不再属于我。
3楼-- · 2018-12-31 13:07

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.

查看更多
素衣白纱
4楼-- · 2018-12-31 13:08

@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.

查看更多
后来的你喜欢了谁
5楼-- · 2018-12-31 13:08

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
    }
}
查看更多
孤独总比滥情好
6楼-- · 2018-12-31 13:09

Without arc4Random_uniform() in some versions of Xcode(in 7.1 it runs but doesn't autocomplete for me). You can do this instead.

To generate a random number from 0-5. First

import GameplayKit

Then

let diceRoll = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
查看更多
皆成旧梦
7楼-- · 2018-12-31 13:10

Use the standard library functions for high quality random numbers: arc4random() or arc4random_uniform(), just as in Objective-C.

They are in the Darwin module, so if you haven't imported AppKit, UIKit, or Foundation (which import it for you), you will need to import Darwin.

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()
查看更多
登录 后发表回答