建议使用arc4random_uniform()
而不是像arc4random() % upper_bound
这样的结构,因为当上限不是2的幂时,它会避免“模偏差”。
偏见有多糟糕?例如,如果我生成上限为6的随机数,那么使用arc4random
与%
和arc4random_uniform()
之间的区别是什么?
答案 0 :(得分:19)
arc4random()返回无符号的32位整数,表示值介于两者之间 0和2 ^ 32-1 = 4 294 967 295.
现在,偏差是由多个子区间创建的 模数不完全适合随机输出范围。 让我们想象一下,一个随机生成器可以创建0到198之间的数字 包括的。你想要0到99之间的数字,因此你计算random()%100, 产生0到99:
0%100 = 0
99%100 = 99
100%100 = 0
198%100 = 98
你看到99是唯一一个只能一次的数字
其他人可以在跑步中两次。这意味着99的概率
正好减半,这也是至少偏差的最坏情况
涉及2个子区间。
因为两个小于范围间隔的所有幂都适合于
2 ^ 32间隔,在这种情况下偏差消失。
含义是模数越小,结果越小 随机输出范围,偏差越小。在你的例子中,6是你的上层 bound(我假设0是下限),所以你使用%7,结果是0-3 发生613 566 757次,而4-6发生613 566 756次 所以0-3是613 566 757/613 566 756 = 1.0000000016298倍可能 比4-6。
虽然似乎容易解雇,但有些实验(尤其是蒙特卡罗) 因为这些看起来不可思议的小而完全是有缺陷的 差异非常重要。
如果所需的输出范围大于,则偏差更大 随机目标范围。请阅读Fisher-Yates shuffle条目 因为很多扑克网站都学到了正常的线性方法 同步随机生成器和坏混洗算法导致了 不可能或非常可能的套牌或更糟糕的,可预测的套牌。