最重要的答案是建议使用switch语句来完成这项工作。但是,如果我要考虑的情况很多,那么代码看起来就很笨拙。我有一个巨大的switch语句,在每种情况下都一遍又一遍地重复非常相似的代码。
当您要考虑的概率很大时,是否有更好,更干净的方法来选择具有一定概率的随机数?(例如〜30)
这是一个Swift实现,受各种答案的影响很大,这些答案会生成具有给定(数字)分布的随机数
对于 Swift 4.2 / Xcode 10 和更高版本(嵌入式解释):
func randomNumber(probabilities: [Double]) -> Int { // Sum of all probabilities (so that we don't have to require that the sum is 1.0): let sum = probabilities.reduce(0, +) // Random number in the range 0.0 <= rnd < sum : let rnd = Double.random(in: 0.0 ..< sum) // Find the first interval of accumulated probabilities into which `rnd` falls: var accum = 0.0 for (i, p) in probabilities.enumerated() { accum += p if rnd < accum { return i } } // This point might be reached due to floating point inaccuracies: return (probabilities.count - 1) }
例子:
let x = randomNumber(probabilities: [0.2, 0.3, 0.5])
返回概率为0.2的0,概率为0.3的1,概率为0.5的2。
let x = randomNumber(probabilities: [1.0, 2.0])
以1/3的概率返回0,以2/3的概率返回1。
对于 Swift 3 / Xcode 8:
func randomNumber(probabilities: [Double]) -> Int { // Sum of all probabilities (so that we don't have to require that the sum is 1.0): let sum = probabilities.reduce(0, +) // Random number in the range 0.0 <= rnd < sum : let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max) // Find the first interval of accumulated probabilities into which `rnd` falls: var accum = 0.0 for (i, p) in probabilities.enumerated() { accum += p if rnd < accum { return i } } // This point might be reached due to floating point inaccuracies: return (probabilities.count - 1) }
对于 Swift 2 / Xcode 7:
func randomNumber(probabilities probabilities: [Double]) -> Int { // Sum of all probabilities (so that we don't have to require that the sum is 1.0): let sum = probabilities.reduce(0, combine: +) // Random number in the range 0.0 <= rnd < sum : let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max) // Find the first interval of accumulated probabilities into which `rnd` falls: var accum = 0.0 for (i, p) in probabilities.enumerate() { accum += p if rnd < accum { return i } } // This point might be reached due to floating point inaccuracies: return (probabilities.count - 1) }