【发布时间】:2009-03-15 22:51:21
【问题描述】:
使用:
value = arc4random() % x
如何避免或消除模偏差?
至少根据 Wikipedia 的说法,在编写概率游戏时,模偏差是一个问题。
【问题讨论】:
-
考虑将 Zoidberg 的答案重新标记为正确答案,因为根据 arc4random() 的作者,这是规范的正确答案。
标签: objective-c random
使用:
value = arc4random() % x
如何避免或消除模偏差?
至少根据 Wikipedia 的说法,在编写概率游戏时,模偏差是一个问题。
【问题讨论】:
标签: objective-c random
使用arc4random_uniform(x)。这是为你做的。
根据手册页:
arc4random_uniform()将返回小于upper_bound的均匀分布随机数。推荐arc4random_uniform()而非arc4random() % upper_bound之类的结构,因为当上限不是 2 的幂时,它可以避免“模偏差”。
【讨论】:
arc4random 返回一个 32 位无符号整数(0 到 232-1)。
对于足够小的 x,可能不会有明显的模偏差。但是,如果您想真正确定,请执行以下操作:
y = 2p 其中 2p-1p
val = arc4random() % y;
while(val >= x)
val = arc4random() % y;
【讨论】:
arc4random_uniform() src/sys/dev/rnd.c 找到
u_int32_t maxValue = ~((u_int32_t) 0); // equal to 0xffff...
maxValue -= maxValue % x; // make maxValue a multiple of x
while((value = arc4random()) >= maxValue) { // loop until we get 0 ≤ value < maxValue
}
value %= x;
尽管除非您使用任何低于一百万(或更多)的 x,否则我不会担心
【讨论】:
如果arc4random mod x 的最大值大于x,则忽略大于最大值arc4random-max mod x 的任何值,而是再次调用arc4random。
【讨论】:
u_int32_t maxValue = ~((u_int32_t) 0); // equal to 0xffff...
maxValue -= maxValue % x; // make maxValue a multiple of x
while((value = arc4random()) >= maxValue) { // loop until we get 0 ≤ value < maxValue
}
value %= x;
对 cobbal 的回答有些迂腐的反对。它“有效”,即它消除了模偏差,但它拒绝了比必要更多的值。最极端的情况是 x = 2^31。 arc4random() 的所有值都应在此处接受,但编写的代码将拒绝其中的一半。
相反,将 1 添加到 maxValue 的初始化(将其置于 2^32,因此您必须使用 64 位 int),然后就对了。您还可以避免使用 64 位 int。预先测试是否 2^32 % x == 0,如果是,则所有 arc4random() 值都可接受,您可以跳过循环,否则您可以通过在初始化时减去 2^32 % x 来保持 maxValue 为 32 位。
【讨论】: