2016-02-17 258 views
5

产生一个随机数我https://www.hackingwithswift.com/read/35/2/generating-random-numbers-in-ios-8-and-earlier读到产生一个随机数的最佳方法是使用斯威夫特

let r = arc4random_uniform(UInt32(_names.count)) 
    let name : String = _names[Int(r)] 

但似乎奇怪的是,我要投两次,才能得到一个随机数,我应该怎么做才能避免施放?

+0

@TroyT:其实也没有参与这个代码铸造。 OP只是从'Int'值创建一个'UInt32'。 –

+0

@TroyT:看看我的扩展。它确实为'Int'添加了一个初始值设定项,它接收一个范围并在该范围内生成一个“Int”。 –

+1

@appzYourLife我upvoted :)比我的答案更可重用。 – tktsubota

回答

6

这真的取决于有多少铸造你希望避免的。你可以简单地将它包装在一个函数中:

func random(max maxNumber: Int) -> Int { 
    return Int(arc4random_uniform(UInt32(maxNumber))) 
} 

那么你只需要做一次丑陋的铸造。无论你想要一个最大数量的随机数:

let r = random(max: _names.count) 
let name: String = _names[r] 

作为一个侧面说明,因为这是斯威夫特,你的属性不会在他们面前需要_

+0

你的'random()'函数不能编译。你必须投射'arc4random_uniform()'的返回值。 –

+0

@MartinR呃,我会解决这个问题。 – tktsubota

1

可以使用gameplaykit

let random = GKRandomDistribution(lowestValue: 0, highestValue: 100) 
let r = random.nextInt() 
+1

这取决于使用情况,Apple文档声明:* GameplayKit中提供的随机化服务适用于可靠地创建确定性,伪随机游戏机制,但**不具有密码稳健**。对于加密,混淆或密码使用,请使用加密服务指南*中介绍的安全框架。 'arc4random()'和'arc4random_uniform()'是密码强健的。 – zaph

0

或者你可以使用

let name : String = _names[ Int(arc4random()) % _names.count ] 
+0

不,使用'arc4random_uniform'来避免模偏差。 – zaph

+0

OP正在从列表中选择一个名称。这很难作为模数偏差可以产生任何相关差异的有效方案。列表中有4096个名字,在一半条目上偏差为0.000096% –

+0

为什么使用'arc4random()'比'arc4random_uniform()'更好。问题是关于使用'arc4random_uniform'投射? – zaph

3

我真的很喜欢使用这个扩展

extension Int { 
    init(random range: Range<Int>) { 

     let offset: Int 
     if range.startIndex < 0 { 
      offset = abs(range.startIndex) 
     } else { 
      offset = 0 
     } 

     let min = UInt32(range.startIndex + offset) 
     let max = UInt32(range.endIndex + offset) 

     self = Int(min + arc4random_uniform(max - min)) - offset 
    } 
} 

现在,您可以生成一个随机Int表示从卢卡

let a = Int(random: 1...10) // 3 
let b = Int(random: 0..<10) // 6 
let c = Int(random: 0...100) // 31 
let d = Int(random: -10...3) // -4 
+0

你可以扩大范围本身http://stackoverflow.com/a/34712601/2303865 –

+1

@LeoDabus:非常好! –

1

修改答案写范围作为Swift 4的延伸

/// Returns random number within given range, upper bound included, eg. -1...0 = [-1, 0, 1] 
extension CountableClosedRange where Bound == Int 
{ 
    var random: Int 
    { 
     let range = self 
     let offset: Int = range.lowerBound < 0 ? abs(range.lowerBound) : 0 
     let min = UInt32(range.lowerBound + offset) 
     let max = UInt32(range.upperBound + offset) 
     let randomNumber = Int(min + arc4random_uniform(max - min + 1)) - offset 

     return randomNumber 
    } 
} 

/// Returns random number within given range, upper bound not included, eg. -1...0 = [-1, 0] 
extension CountableRange where Bound == Int 
{ 
    var random: Int 
    { 
     let range = self 
     let offset: Int = range.lowerBound < 0 ? abs(range.lowerBound) : 0 
     let min = UInt32(range.lowerBound + offset) 
     let max = UInt32(range.upperBound + offset) 
     let randomNumber = Int(min + arc4random_uniform(max - min)) - offset 

     return randomNumber 
    } 
} 

例子:

(0...10).random 
(0..<10).random