Arc4random模数偏差

时间:2013-07-14 15:10:06

标签: objective-c random probability arc4random

根据this documentation

  建议使用arc4random_uniform()而不是像arc4random() % upper_bound这样的结构,因为当上限不是2的幂时,它会避免“模偏差”。

偏见有多糟糕?例如,如果我生成上限为6的随机数,那么使用arc4random%arc4random_uniform()之间的区别是什么?

1 个答案:

答案 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条目 因为很多扑克网站都学到了正常的线性方法 同步随机生成器和坏混洗算法导致了 不可能或非常可能的套牌或更糟糕的,可预测的套牌。