使用:
value = arc4random() % x
如何避免或消除模偏差?
至少根据维基百科的说法,在编制机会游戏时,模偏差是一个问题。
答案 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