Подтвердить что ты не робот

Objective-C: смещение по модулю

С помощью:

value = arc4random() % x

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

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

4b9b3361

Ответ 1

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

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

Согласно странице руководства:

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

Ответ 3

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 менее миллиона (или более), я бы не стал беспокоиться об этом

Ответ 4

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

Ответ 5

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

Ответ 6

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

ЕСЛИ вы хотите 4-7:

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

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

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