一尘不染

Swift-播种arc4random_uniform?还是另类?

swift

让我首先说明我要完成的工作:

  1. 我需要随机生成一个范围内的一组数字
  2. 我希望这些数字可以均匀分布
  3. 我需要能够为随机数生成提供种子,以便在获得种子的情况下,所得的随机数将始终相同。

在对drand48(),rand()和arc4random()进行了大量实验之后,我目前决定使用rand()获得随机数,并使用srand()进行播种。这是从我正在做的事情简化的一个小例子:

let seed: UInt32 = 10
srand(seed)
let start = 0
let end = 100
let randomNumber = Double(rand()) % (end + 1 - start) + start

这可行。给定相同的种子,就会产生相同的随机数。执行多个randomNumber计算会导致出现多个不同的随机数。通过srand重新播种会再次开始“随机性”。

唯一的缺点是rand()不是均匀分布的。确实,我几乎总是总是得到一组在很大程度上线性增长的数字。

听起来arc4random_uniform会生成更多均匀的随机输出,但是根据我的研究,无法播种arc4random,因为它是在第一次调用时就本身进行播种,并且不一定要“设计”为外部播种。

所以我的问题;有没有比srand()/ rand()更好的替代方法,它仍然可以为给定的种子提供相同的输出,但是这些输出分布更均匀?

谢谢-亚当


阅读 305

收藏
2020-07-07

共1个答案

一尘不染

事实证明,srand / rand组合可以满足我的需求,导致结果显示不“均匀分布”的问题是我自己的逻辑中的一个错误。

供参考,本质上我是在做这件事(实际上,它要复杂得多,但出于演示目的):

let start = 0
let end = 100

for x in 0..<10 {

   let seed = UInt32(x)
   srand(seed)
   let randomNumber = Double(rand()) % (end + 1 - start) + start

   // Do something with random number

}

用上面更简单的形式编写的问题变得很明显。我在循环的每次迭代中都重新播种,种子值只是线性增加。因此,随机结果也呈线性增加。

简单的解决方案是不重新种子每次循环迭代,而是在循环之前种子一次。例如:

let start = 0
let end = 100
let seed = UInt32(100)
srand(seed)

for x in 0..<10 {

   let randomNumber = Double(rand()) % (end + 1 - start) + start

   // Do something with random number

}

通过此简单的更改,结果值似乎在示例中使用的0到100范围内确实均匀分布。我不能确定是否有“更统一”的方式来做到这一点,但是我认为这是因为我读过arc4random比drand
/ rand / erand / etc函数“更优越”,以产生统一的随机数,但是至少这似乎符合我的需求。

如果其他人想出一种更好的方法来实现我所追求的目标,我将把这个问题搁置一段时间。

2020-07-07