Objective-C: смещение по модулю - PullRequest
13 голосов
/ 16 марта 2009

Использование:

value = arc4random() % x

Как мне избежать или устранить смещение по модулю?

По крайней мере, согласно Википедии, смещение по модулю является проблемой при программировании азартных игр.

Ответы [ 6 ]

49 голосов
/ 01 июня 2011

Используйте arc4random_uniform(x). Это делает это для вас.

Согласно справочной странице:

arc4random_uniform() вернет равномерно распределенное случайное число, меньшее upper_bound. arc4random_uniform() рекомендуется для таких конструкций, как arc4random() % upper_bound, поскольку это позволяет избежать "смещения по модулю", когда верхняя граница не является степенью двойки.

14 голосов
/ 16 марта 2009

arc4random возвращает 32-разрядное целое число без знака (от 0 до 2 32 -1).

Вероятно, не будет заметного смещения по модулю для достаточно малого x. Однако, если вы хотите быть действительно уверенным, сделайте следующее:

y = 2 p , где 2 p-1 p

val = arc4random() % y;
while(val >= x)
    val = arc4random() % y;
4 голосов
/ 16 марта 2009
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 меньше миллиона (или больше), я бы об этом не беспокоился

2 голосов
/ 16 марта 2009

Если максимальное значение arc4random mod x больше x, игнорируйте любые значения, большие чем arc4random-max mod x, вызывая вместо этого arc4random.

1 голос
/ 18 января 2011
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 = 2 ^ 31. Все значения arc4random () должны быть приняты здесь, но код, как написано, отклонит половину из них.

Вместо этого, добавьте 1 к инициализации maxValue (который устанавливает его в 2 ^ 32, так что вам придется использовать 64-битное целое число), и тогда это правильно. Вы также можете избежать использования 64-битного int. Проверьте заранее, если 2 ^ 32% x == 0, если так, все значения arc4random () являются приемлемыми, и вы можете пропустить цикл, в противном случае вы можете сохранить значение maxValue в 32 битах, вычитая 2 ^ 32% x при инициализации.

0 голосов
/ 05 января 2013

Используйте метод ниже. Избегает "смещения по модулю" и это быстро на iphone. Сохраните несколько циклов процессора.

Если вы хотите 4-7:

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

ИЛИ если вы хотите 0-8

(random() / (float)RAND_MAX )+8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...