2009-03-15 12 views
14

UsandoC Objetivo: Modulo sesgo

value = arc4random() % x 

¿Cómo puedo evitar o eliminar el sesgo de módulo?

Gracias a todos.

Por cierto, al menos según Wikipedia, el sesgo del módulo es un problema cuando se programan juegos de azar .

+1

posibilidad de volver a marcar la respuesta de Zoidberg como la correcta, ya que es la respuesta correcta canónica según los autores de arc4random(). – MikeyWard

+2

[¿Qué es un sesgo de módulo] (http://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator)? – bobobobo

Respuesta

14

arc4random devuelve un entero sin signo de 32 bits (0 a 2 -1).

Probablemente no habrá un sesgo de módulo notable para una x suficientemente pequeña. Sin embargo, si quieres estar realmente seguro, haga lo siguiente:

y = 2 p donde 2 p-1 < x ≤ 2 p

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

De nada. =) –

+0

Si no recuerdo mal, hay algo como esto en el generador de números aleatorios de Python. –

+3

Ocurro tropezar con la misma tarea, la implementación C se puede encontrar en OpenBSD 'arc4random_uniform()' en [src/sys/dev/rnd.c] (http://www.openbsd.org/cgi-bin/cvsweb/ src/sys/dev/rnd.c? rev = 1.140; content-type = text% 2Flain) – SashaN

2

Si el valor máximo de arc4random mod x es mayor que x, ignore cualquier valor mayor que el arc4random-max mod x más grande, llamando al arc4random nuevamente.

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; 

aunque menos que esté utilizando cualquier x menos de un millón (o más) yo no me preocuparía por eso

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; 

objeción Un poco pedante a la respuesta de cobbal. "Funciona", es decir, elimina el sesgo del módulo, pero rechaza más valores de los necesarios. El caso más extremo es x = 2^31. Todos los valores de arc4random() deberían aceptarse aquí, pero el código tal como está escrito rechazará la mitad de ellos.

En su lugar, agregue 1 a la inicialización de maxValue (que lo pone en 2^32 por lo que tendrá que usar un int de 64 bits), y luego está bien. También puede evitar el uso de un int de 64 bits. Pruebe de antemano si 2^32% x == 0, si es así, todos los valores de arc4random() son aceptables y puede omitir el bucle; de ​​lo contrario, puede mantener maxValue en 32 bits restando 2^32% x en la inicialización.

47

Use arc4random_uniform(x). Esto lo hace por ti.

Según la página hombre:

arc4random_uniform() devolverá un número aleatorio distribuido uniformemente menos de upper_bound. arc4random_uniform() se recomienda en construcciones como arc4random() % upper_bound ya que evita el "sesgo de módulo" cuando el límite superior no es una potencia de dos.

+5

Esta respuesta es mejor que la aceptada. –

-1

Utilice el siguiente método. Evita el "sesgo de módulo" y es rápido en iphone. Ahorre algunos ciclos de CPU.

SI usted quiere 4-7:

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

o si desea 0-8

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

'random()' no es un generador seguro de números aleatorios, ¡no lo use! – dchest