生成具有给定分布的随机数 [英] Generate random numbers with a given distribution
问题描述
查看这个问题:
最高的答案建议使用switch语句,它执行作业。但是,如果我有大量的案例需要考虑,代码看起来很不真实;我有一个巨大的开关语句,非常相似的代码在每种情况下重复一遍又一遍。
有一个更好的,更清洁的方式来选择一个随机数有一定的概率当你有大量的可能性要考虑? (像〜30)
这是一个Swift实现强烈影响的各种
答案使用给定(数字)分布生成随机数字:
func randomNumber(#probabilities:[Double]) - > int {
//所有概率的总和(所以我们不必要求和为1.0):
let sum = reduce(probabilities,0,+)
//范围内的随机数0.0< = rnd< sum:
let rnd = sum * Double(arc4random_uniform(UInt32.max))/ Double(UInt32.max)
//找到第一个rnd的概率累积间隔:
var accum = 0.0
for(i,p)in enumerate(probabilities){
accum + = p
if rnd<因为浮点不准确,可能会达到这一点:$ b $ b return(probabilities.count - 1)
$ b}
示例:
let x = randomNumber(probabilities:[0.2,0.3,0.5])
返回0的概率为0.2,1的概率为0.3,
和2的概率为0.5。
let x = randomNumber (概率:[1.0,2.0])
以概率1/3返回0, / 3。 Swift 2 / Xcode 7:
$ b更新 func randomNumber(probabilities probability:[Double]) - > int {
//所有概率的总和(所以我们不必要求和为1.0):
let sum = probabilities.reduce(0,combine:+)
//范围内的随机数0.0< = rnd< sum:
let rnd = sum * Double(arc4random_uniform(UInt32.max))/ Double(UInt32.max)
//找到第一个rnd的概率累积间隔:
var accum = 0.0
for(i,p)in probabilities.enumerate(){
accum + = p
if rnd<因为浮点不准确,可能会达到这一点:$ b $ b return(probabilities.count - 1)
$ b}
更新 Swift 3 / Xcode 8:
func randomNumber(probabilities:[Double]) - > int {
//所有概率的总和(所以我们不必要求和为1.0):
let sum = probabilities.reduce(0,+)
//范围内的随机数0.0< = rnd< sum:
let rnd = sum * Double(arc4random_uniform(UInt32.max))/ Double(UInt32.max)
//找到第一个rnd的概率累积间隔:
var accum = 0.0
for(i,p)in probabilities.enumerated(){
accum + = p
if rnd<因为浮点不准确,可能会达到这一点:$ b $ b return(probabilities.count - 1)
$ b}
Check out this question:
Swift probability of random number being selected?
The top answer suggests to use a switch statement, which does the job. However, if I have a very large number of cases to consider, the code looks very inelegant; I have a giant switch statement with very similar code in each case repeated over and over again.
Is there a nicer, cleaner way to pick a random number with a certain probability when you have a large number of probabilities to consider? (like ~30)
This is a Swift implementation strongly influenced by the various answers to Generate random numbers with a given (numerical) distribution:
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 = reduce(probabilities, 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 enumerate(probabilities) {
accum += p
if rnd < accum {
return i
}
}
// This point might be reached due to floating point inaccuracies:
return (probabilities.count - 1)
}
Examples:
let x = randomNumber(probabilities: [0.2, 0.3, 0.5])
returns 0 with probability 0.2, 1 with probability 0.3, and 2 with probability 0.5.
let x = randomNumber(probabilities: [1.0, 2.0])
return 0 with probability 1/3 and 1 with probability 2/3.
Update for 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)
}
Update for 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)
}
这篇关于生成具有给定分布的随机数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!