当前位置: 首页 > 工具软件 > Swift-T > 使用案例 >

Swift - 随机数生成

卢鸿博
2023-12-01

随机数的生成一直是程序员面临的一个大问题,在由CPU 时钟进程线程所构建出的世界中,是没有真正的随机的。在给定一个随机种子后,使用某些神奇的算法我们可以得到一组随机的序列

arc4random 是一个非常优秀的随机数算法,并且在Swift 中也可以使用。它会返回给我们一个任意整数,我们想要某个范围里的数的话,做模运算(%)取余数就行了。

uint32_t arc4random(void);

但在使用arc4random 函数的时候,有时候程序会崩溃,请注意这个“有时候”

最让程序员郁闷的事情莫过于程序有时候会崩溃而有时候又能良好运行。还好这里的情况比较简单,聪明的我们马上就能指出原因。其实Swift 的Int 是和CPU 架构有关的:在32 位的CPU 上,它实际上是Int32,而在64 为的CPU 上是Int64arc4random 所返回的值不论在什么平台上都是一个UInt32,于是在32 位的平台上就有一半的概率在进行Int 转换越界,时不时出现的崩溃也就不足为奇了。

这种情况下,一种相对安全的做法是使用一个arc4random改良版本

uint32_t
	 arc4random_uniform(uint32_t __upper_bound) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);

这个改良版本接受一个UInt32数字n 作为输入,将结果归化到0n - 1 之间。只要我们的输入不超过Int 的范围,就可以避免危险的转换:

let diceFacecount: UInt32 = 6
let randomRoll = Int(arc4random_uniform(diceFacecount)) + 1
print(randomRoll)

最佳实践当然是为Range 创建一个生成随机数的方法的随机数方法,这样我们就能在之后很容易的复用,甚至设计类似Randomable 这样的接口了:

func randomInRange(_ range: Range<Int>) -> Int {
    let count = UInt32(range.endIndex - range.startIndex)
    return Int(arc4random_uniform(count)) + range.startIndex
}

for _ in 0...100 {
    print(randomInRange(1..<6))
}
 类似资料: