Objective-C:模偏差

时间:2009-03-15 22:51:22

标签: objective-c random

使用:

value = arc4random() % x

如何避免或消除模偏差?

至少根据维基百科的说法,在编制机会游戏时,模偏差是一个问题。

6 个答案:

答案 0 :(得分:49)

使用arc4random_uniform(x)。这适合你。

根据手册页:

  

arc4random_uniform()将返回小于upper_bound的均匀分布的随机数。建议使用arc4random_uniform()而不是像arc4random() % upper_bound这样的结构,因为当上限不是2的幂时,它会避免“模偏差”。

答案 1 :(得分:14)

arc4random返回一个32位无符号整数(0到2 32 -1)。

对于足够小的x,可能没有明显的模偏差。但是,如果你想确定,请执行以下操作:

y = 2 p 其中2 p-1 < x≤2 p

val = arc4random() % y;
while(val >= x)
    val = arc4random() % y;

答案 2 :(得分:4)

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不到一百万(或更多)我不会担心它

答案 3 :(得分:2)

如果arc4random mod x的最大值大于x,请忽略大于最大arc4random-max mod x的任何值,而是再次调用arc4random

答案 4 :(得分:1)

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()的所有值,但是所写的代码将拒绝其中的一半。

相反,在maxValue的初始化中添加1(将其置于2 ^ 32,因此您将不得不使用64位int),然后它是正确的。您还可以避免使用64位int。事先测试2 ^ 32%x == 0,如果是这样,所有arc4random()值都可以接受,你可以跳过循环,否则你可以通过在初始化时减去2 ^ 32%x来保持maxValue为32位。

答案 5 :(得分:-2)

使用以下方法。它避免了“模偏” 它在iphone上很快。节省一些cpu周期。

如果您想要4-7:

(random() / (float)RAND_MAX )*3+4

或者如果你想要0-8

(random() / (float)RAND_MAX )+8