我意识到Swift书籍提供了一个随机数生成器的实现。复制和粘贴这个实现是最佳实践吗?或者有没有这样的库,我们现在就可以使用?


当前回答

这里有一个库可以很好地完成这项工作 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
    }
}

其他回答

我已经能够使用rand()来获得一个随机的CInt。你可以使用这样的方法使它成为Int型:

let myVar: Int = Int(rand())

你可以使用你最喜欢的C随机函数,并在需要时将值转换为Int。

你可以像在C中那样做:

let randomNumber = arc4random()

推断randomNumber类型为UInt32(32位无符号整数)

在某些版本的Xcode中没有arc4Random_uniform()(在7.1中运行,但对我来说不自动完成)。你可以这样做。

从0-5中生成一个随机数。 第一个

import GameplayKit

Then

let diceRoll = GKRandomSource.sharedRandom().nextIntWithUpperBound(6)

使用arc4random_uniform ()

用法:

arc4random_uniform(someNumber: UInt32) -> UInt32

这将为您提供0到someNumber - 1范围内的随机整数。

UInt32的最大值为4,294,967,295(即2^32 - 1)。

例子:

抛硬币 让flip = arc4random_uniform(2) // 0或1 骰子滚 Let roll = arc4random_uniform(6) + 1 // 1 十月的任意一天 Let day = arc4random_uniform(31) + 1 // 1 90年代的任意一年 Let year = 1990 + arc4random_uniform(10)

一般形式:

let number = min + arc4random_uniform(max - min + 1)

其中number、max、min为UInt32。

是什么……

arc4random ()

你也可以通过使用arc4random()得到一个随机数,它会产生一个在0到2^32-1之间的UInt32。因此,要得到一个介于0和x-1之间的随机数,可以将其除以x并取余数。或者换句话说,使用余数运算符(%):

let number = arc4random() % 5 // 0...4

然而,这会产生轻微的模数偏差(参见这里和这里),所以这就是为什么建议使用arc4random_uniform()。

从Int转换到Int

通常情况下,为了在Int和UInt32之间来回转换,这样做是很好的:

let number: Int = 10
let random = Int(arc4random_uniform(UInt32(number)))

但问题是,Int的范围是-2,147,483,648…2,147,483,647在32位系统和范围-9,223,372,036,854,775,808…9223,372,036,854,775,807在64位系统上。将其与0…4,294,967,295的UInt32范围进行比较。U (UInt32)表示无符号。

考虑以下错误:

UInt32(-1) // negative numbers cause integer overflow error
UInt32(4294967296) // numbers greater than 4,294,967,295 cause integer overflow error

所以你只需要确保你的输入参数是在UInt32范围内,你不需要输出是在这个范围之外。

更新日期:2022年6月9日。

斯威夫特5.7

假设我们有一个数组:

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

对于iOS和macOS,你可以在Xcode的框架GameKit中使用系统范围内的随机源代码。在这里你可以找到GKRandomSource类及其sharerandom()类方法:

import GameKit

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

randomNumberGenerator()

你也可以使用randomElement()方法返回一个集合的随机元素:

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

或者使用arc4random_uniform()。注意,该方法返回UInt32类型。

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

当然,我们也可以使用makeIterator()方法,该方法返回集合元素上的迭代器。

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

你在这里看到的最后一个例子通过静态func random(in range: ClosedRange<Int>) -> Int在指定范围内返回一个随机值。

let randomizer = Int.random(in: 1...10)
print(randomizer)

伪随机双位数生成器drand48()返回0.0到1.0之间的值。

import Foundation

let randomInt = Int(drand48() * 10)