Swift 如何在Apple';什么是快速的语言?

Swift 如何在Apple';什么是快速的语言?,swift,random,Swift,Random,我意识到Swift手册提供了一个随机数生成器的实现。将此实现复制并粘贴到自己的程序中是最佳做法吗?或者有一个库可以这样做,我们现在可以使用吗?我已经能够使用rand()来获得一个随机的CInt。您可以使用如下方法将其设置为Int: let myVar: Int = Int(rand()) 您可以使用您最喜欢的C随机函数,如果需要,只需将value转换为Int即可。您可以使用与C相同的方法: let randomNumber = arc4random() randomNumber被推断为类型U

我意识到Swift手册提供了一个随机数生成器的实现。将此实现复制并粘贴到自己的程序中是最佳做法吗?或者有一个库可以这样做,我们现在可以使用吗?

我已经能够使用
rand()
来获得一个随机的CInt。您可以使用如下方法将其设置为Int:

let myVar: Int = Int(rand())

您可以使用您最喜欢的C随机函数,如果需要,只需将value转换为Int即可。

您可以使用与C相同的方法:

let randomNumber = arc4random()

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

Swift 4.2+

Xcode 10附带的Swift 4.2为许多数据类型引入了新的易于使用的随机函数。 可以对数值类型调用
random()
方法

let randomInt = Int.random(in: 0..<6)
let randomDouble = Double.random(in: 2.71828...3.14159)
let randomBool = Bool.random()

让randomInt=Int.random(in:0..使用
arc4random_uniform(n)
表示0到n-1之间的随机整数

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

将结果强制转换为Int,这样您就不必显式地将VAR键入为
UInt32
(这似乎不快速)。

为Swift 4.2编辑

从Swift 4.2开始,不再使用导入的C函数arc4random_uniform(),现在可以使用Swift自己的本机函数

// Generates integers starting with 0 up to, and including, 10
Int.random(in: 0 ... 10)
您可以使用
random(in:)
为其他基本值获取随机值;例如Int、Double、Float甚至Bool

Swift版本<4.2

此方法将生成给定最小值和最大值之间的随机
Int

func randomInt(min: Int, max: Int) -> Int {
    return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}
编辑:

arc4random
在Swift中运行良好,但基本函数仅限于32位整数类型(
Int
在iPhone 5S和现代Mac上为64位)。以下是一个通用函数,用于表示可由整数文本表示的类型的随机数:

public func arc4random<T: ExpressibleByIntegerLiteral>(_ type: T.Type) -> T {
    var r: T = 0
    arc4random_buf(&r, MemoryLayout<T>.size)
    return r
}
有了它,我们可以为相同的参数扩展
Int64
,处理溢出:

public extension Int64 {
    public static func random(lower: Int64 = min, upper: Int64 = max) -> Int64 {
        let (s, overflow) = Int64.subtractWithOverflow(upper, lower)
        let u = overflow ? UInt64.max - UInt64(~s) : UInt64(s)
        let r = UInt64.random(upper: u)

        if r > UInt64(Int64.max)  {
            return Int64(r - (UInt64(~lower) + 1))
        } else {
            return Int64(r) + lower
        }
    }
}
为了完成这个家庭

private let _wordSize = __WORDSIZE

public extension UInt32 {
    public static func random(lower: UInt32 = min, upper: UInt32 = max) -> UInt32 {
        return arc4random_uniform(upper - lower) + lower
    }
}

public extension Int32 {
    public static func random(lower: Int32 = min, upper: Int32 = max) -> Int32 {
        let r = arc4random_uniform(UInt32(Int64(upper) - Int64(lower)))
        return Int32(Int64(r) + Int64(lower))
    }
}

public extension UInt {
    public static func random(lower: UInt = min, upper: UInt = max) -> UInt {
        switch (_wordSize) {
            case 32: return UInt(UInt32.random(UInt32(lower), upper: UInt32(upper)))
            case 64: return UInt(UInt64.random(UInt64(lower), upper: UInt64(upper)))
            default: return lower
        }
    }
}

public extension Int {
    public static func random(lower: Int = min, upper: Int = max) -> Int {
        switch (_wordSize) {
            case 32: return Int(Int32.random(Int32(lower), upper: Int32(upper)))
            case 64: return Int(Int64.random(Int64(lower), upper: Int64(upper)))
            default: return lower
        }
    }
}
在所有这些之后,我们终于可以这样做:

let diceRoll = UInt64.random(lower: 1, upper: 7)
var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
    _ -> Int? in
    fibs.append(fibs.reduce(0, combine:+))
    return fibs.removeAtIndex(0)
}

println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
GKRandomSource.sharedRandom().nextInt()
let d6 = GKRandomDistribution.d6()
d6.nextInt()
print(UInt8.random)
我使用了以下代码:

var k: Int = random() % 10;

此处5将确保通过0到4生成随机数。您可以相应地设置值。

您可以像这样使用
GeneratorOf

let diceRoll = UInt64.random(lower: 1, upper: 7)
var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
    _ -> Int? in
    fibs.append(fibs.reduce(0, combine:+))
    return fibs.removeAtIndex(0)
}

println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
GKRandomSource.sharedRandom().nextInt()
let d6 = GKRandomDistribution.d6()
d6.nextInt()
print(UInt8.random)

我想补充现有答案,Swift书中的随机数生成器示例是线性同余生成器(LCG),这是一个非常有限的例子,不应该被排除在少数几个小例子之外,在这些例子中,随机性的质量根本不重要。LCG不应该用于加密目的

arc4random()
要好得多,可以用于大多数目的,但同样不应用于加密目的。


如果你想保证加密的东西,请使用<代码> ScCopyRyByType()/<代码>注意,如果你将一个随机数生成器构建成某个东西,其他人可能会终止(MIS)-使用它作为密码目的(例如密码、密钥或盐生成),那么你应该考虑使用<代码> ScCopReavyByt()

无论如何,即使您的需求不太需要。

从iOS 9开始,您可以使用新的GameplayKit类以多种方式生成随机数

您有四种源类型可供选择:普通随机源(未命名,由系统选择其功能)、线性全等、ARC4和Mersenne Twister。它们可以生成随机整数、浮点和布尔

在最简单的级别上,您可以从系统的内置随机源生成一个随机数,如下所示:

let diceRoll = UInt64.random(lower: 1, upper: 7)
var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
    _ -> Int? in
    fibs.append(fibs.reduce(0, combine:+))
    return fibs.removeAtIndex(0)
}

println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
GKRandomSource.sharedRandom().nextInt()
let d6 = GKRandomDistribution.d6()
d6.nextInt()
print(UInt8.random)
这将生成一个介于-2147483648和2147483647之间的数字。如果您想要一个介于0和上限(独占)之间的数字,请使用以下选项:

GKRandomSource.sharedRandom().nextIntWithUpperBound(6)
GameplayKit内置了一些方便的构造器来处理骰子。例如,您可以像这样滚动六面骰子:

let diceRoll = UInt64.random(lower: 1, upper: 7)
var fibs = ArraySlice([1, 1])
var fibGenerator = GeneratorOf{
    _ -> Int? in
    fibs.append(fibs.reduce(0, combine:+))
    return fibs.removeAtIndex(0)
}

println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
println(fibGenerator.next())
GKRandomSource.sharedRandom().nextInt()
let d6 = GKRandomDistribution.d6()
d6.nextInt()
print(UInt8.random)
此外,您还可以使用GKShuffledDistribution之类的工具来塑造随机分布。这需要更多的解释,但如果您感兴趣,您可以。

使用
arc4random\u uniform()
用法:

let number = min + arc4random_uniform(max - min + 1)
arc4random\u统一(某些数字:UInt32)->UInt32

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

UInt32
的最大值为4294967295(即
2^32-1

示例:

let number = min + arc4random_uniform(max - min + 1)
  • 投币

      let flip = arc4random_uniform(2) // 0 or 1
    
  • 骰子卷

      let roll = arc4random_uniform(6) + 1 // 1...6
    
  • 十月的随机日

      let day = arc4random_uniform(31) + 1 // 1...31
    
  • 1990年代的随机年份

      let year = 1990 + arc4random_uniform(10)
    
一般形式:

let number = min + arc4random_uniform(max - min + 1)
其中,
number
max
min
UInt32

let generator = Int(arc4random_uniform(10))
print(generator)
那么...怎么样 arc4random()

您还可以使用
arc4random()
获得一个随机数,该随机数产生一个介于0和2^32-1之间的
UInt32
。因此,要获得介于
0
x-1
之间的随机数,您可以将其除以
x
,然后取余数。或者换句话说,使用:

但是,这会产生轻微的影响(另请参见和),因此建议使用
arc4random\u uniform()

Int的转换

通常,这样做可以在
Int
UInt32
之间来回转换:

let number: Int = 10
let random = Int(arc4random_uniform(UInt32(number)))
但问题是,在32位系统上的范围是
-2147483648…2147483647
,而在64位系统上的范围是
-9223372036854775808…9223372036854775807
。将其与
UInt32
范围
0…4294967295
进行比较。
UInt32
U
表示无符号

考虑以下错误:

UInt32(-1) // negative numbers cause integer overflow error
UInt32(4294967296) // numbers greater than 4,294,967,295 cause integer overflow error
因此,您只需确保输入参数在
UInt32
范围内,并且不需要输出为ou
let randInt = Int.random(in: 1..<10)
let randFloat = Float.random(in: 1..<20)
let randDouble = Double.random(in: 1...30)
let randCGFloat = CGFloat.random(in: 1...40)
let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomDouble = Double.random(in: 1 ... 10)
let intBetween0to9 = Int.random(in: 0...9) 
let doubleBetween0to1 = Double.random(in: 0...1)
let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
import GameKit

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

randomNumberGenerator()
let randomNumber = numbers.randomElement()!
print(randomNumber)
let generator = Int(arc4random_uniform(10))
print(generator)
let iterator: Int = (1...10).makeIterator().shuffled().first!
print(iterator)
let randomizer = Int.random(in: 1...10)
print(randomizer)
// 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()