发表于分类于iOS
,
Swift
,
random阅读次数:Valine: 本文字数:7.4k阅读时长 ≈7 分钟
在Swift中生成随机数
使用最新方法并涵盖一些旧技术,了解在 Swift 中生成随机值所需的一切。
如何使用Swift生成随机数?
幸运的是,自 Swift 4.2 起,统一了随机数生成功能。 这意味着你不再需要导入的 C API ,只需在所有平台上使用本机 Swift 方法即可生成随机值! 😍
1 2 3 4
let randomBool = Bool.random() let randomInt = Int.random(in: 1...6) //dice roll let randomFloat = Float.random(in: 0...1) let randomDouble = Double.random(in: 1..<100)
如你所见,借助 Swift语言 内置的加密安全随机发生器,现在非常容易生成骰子。 新的随机数生成器 API 也更擅长分配数字。 旧的 arc4random 函数存在一些问题,因为由于模偏差的影响,生成的值不均匀地分布在例如1到6之间。 🎲
你可以简单地在上述任何一个源上使用 nextInt() 方法从 int min 到 int max 生成一个随机数,或者使用 nextInt(upperBound:) 方法从0到上限生成一个随机数。
1 2 3 4 5 6 7 8 9
import GameplayKit
let arc4 = GKARC4RandomSource() arc4.dropValues(1024) //drop first 1024 values first arc4.nextInt(upperBound: 20) let linearCongruential = GKLinearCongruentialRandomSource() linearCongruential.nextInt(upperBound: 20) let mersenneTwister = GKMersenneTwisterRandomSource() mersenneTwister.nextInt(upperBound: 20)
// 6 sided dice let randomD6 = GKRandomDistribution.d6() let shuffledD6 = GKShuffledDistribution.d6() let gaussianD6 = GKGaussianDistribution.d6() randomD6.nextInt() // completely random shuffledD6.nextInt() // see below... // eg. 1 gaussianD6.nextInt() // mostly 3, most likely 2, 4 less likely 1, 6
//goes through all the possible values again and again... shuffledD6.nextInt() // eg. 3 shuffledD6.nextInt() // eg. 5 shuffledD6.nextInt() // eg. 2 shuffledD6.nextInt() // eg. 6 shuffledD6.nextInt() // eg. 4
// 20 sided dice let randomD20 = GKRandomDistribution.d20() let shuffledD20 = GKShuffledDistribution.d20() let gaussianD20 = GKGaussianDistribution.d20() randomD20.nextInt() shuffledD20.nextInt() gaussianD20.nextInt()
// using custom random source, by default it uses arc4 let mersenneTwister = GKMersenneTwisterRandomSource() let mersoneTwisterRandomD6 = GKRandomDistribution(randomSource: mersenneTwister, lowestValue: 1, highestValue: 6) mersoneTwisterRandomD6.nextInt() mersoneTwisterRandomD6.nextInt(upperBound: 3) //limiting upper bound
let sharedRandomSource = GKRandomSource.sharedRandom() sharedRandomSource.nextBool() // true / false sharedRandomSource.nextInt() //from int min - to int max sharedRandomSource.nextInt(upperBound: 6) //dice roll sharedRandomSource.nextUniform() //float between 0 - 1
此方法将返回均匀分布的随机数。 这是在 Swift 4.2 之前生成随机数的最佳/推荐方式,因为如果上限不是2的幂,它可以避免模偏差问题。
1 2 3 4 5 6 7 8 9 10
funcrndm(min: Int, max: Int) -> Int { ifmax < min { fatalError("The max value should be greater than the min value.") } ifmin == max { returnmin } returnInt(arc4random_uniform(UInt32((max - min) + 1))) + min } rndm(min: 1, max: 6) //dice roll
publicfuncrndm(to max: Int, from min: Int = 0) -> Int { #if os(iOS) || os(tvOS) || os(macOS) || os(watchOS) let scale = Double(arc4random()) / Double(UInt32.max) #endif #if os(Linux) let scale = Double(rand()) / Double(RAND_MAX) #endif var value = max - min let maximum = value.addingReportingOverflow(1) if maximum.overflow { value = Int.max } else { value = maximum.partialValue } let partial = Int(Double(value) * scale) let result = partial.addingReportingOverflow(min) if result.overflow { return partial } return result.partialValue }
rndm(to: 6)
现在我们已经有了 Swift 4.2 ,我想鼓励大家改编新的随机数生成 API方法 。 我非常高兴 苹果公司和社区 能够很好地解决这个问题,结果令人赞叹! 👏👏👏