En una pequeña aplicación escrita en C / C ++, estoy enfrentando un problema con la rand
función y tal vez la semilla:
Quiero producir una secuencia de números aleatorios que sean de diferentes órdenes, es decir, con diferentes valores de logaritmo (base 2). Pero parece que todos los números producidos son del mismo orden, fluctuando solo entre 2 ^ 25 y 2 ^ 30.
¿Es porque rand()
se siembra con el tiempo Unix que ahora es un número relativamente grande? ¿Qué me estoy olvidando? Estoy sembrando rand()
solo una vez al comienzo de la main()
.
rand()
devolver números distribuidos uniformemente (la documentación con un alto ranking de Google lo dice explícitamente) no creo que esta pregunta sea útil para futuros lectores. Es por eso que rechazar el voto, pero no dejes que te desanime a usar SO.Respuestas:
Solo hay un 3% de números entre 1 y 2 30 que NO están entre 2 25 y 2 30 . Entonces, esto suena bastante normal :)
Debido 2 25 /2 30 = 2 -5 = 1/32 = 0,03125 = 3,125%
fuente
>>
desplazamiento de bits, esto le dará números más pequeños. (O tomando un módulo con%
.)0
- y si cada bit es aleatorio ...El verde más claro es la región entre 0 y 2 25 ; el verde más oscuro es la región entre 2 25 y 2 30 . Las garrapatas son poderes de 2.
fuente
Debe ser más preciso: desea valores de logaritmo de base 2 diferentes, pero ¿qué distribución desea para esto? Las funciones estándar rand () generan una distribución uniforme, necesitará transformar esta salida utilizando la función cuantil asociada con la distribución que desee.
Si nos dice la distribución, entonces podemos decirle la
quantile
función que necesita.fuente
Si desea diferentes órdenes de magnitud, ¿por qué no simplemente intentarlo
pow(2, rand())
? ¿O tal vez elegir el orden directamente como rand (), como sugirió Harold?fuente
rand()
puede subirRAND_MAX
, realmente necesita escalar su número aleatorio para que el resultado no se desborde ...@ C4stor hizo un gran punto. Pero, para un caso más general y más fácil de entender para humanos (base 10): para el rango de 1 a 10 ^ n, ~ 90% de los números son de 10 ^ (n-1) a 10 ^ n, por lo tanto, ~ 99% de los números van de 10 ^ (n-2) a 10 ^ n. Sigue agregando tantos decimales como quieras.
Matemáticas divertidas, si sigues haciendo esto para n, puedes ver que de 1 a 10 ^ n, 99.9999 ...% = 100% de los números son de 10 ^ 0 a 10 ^ n con este método.
Ahora sobre el código, si desea un número aleatorio con órdenes de magnitud aleatorios, de 0 a 10 ^ n, puede hacer:
Genere un pequeño número aleatorio de 0 a n
Si conoce el rango que tiene n, genere un gran número aleatorio de orden 10 ^ k donde k> max {n}.
Corte el número aleatorio más largo para obtener los n dígitos de este gran número aleatorio.
fuente
La respuesta básica (y correcta) ya fue dada y aceptada arriba: hay 10 números entre 0 y 9, 90 números entre 10 y 99, 900 entre 100 y 999, etc.
Para obtener una manera computacionalmente eficiente de obtener una distribución con una distribución aproximadamente logarítmica, desea desplazar a la derecha su número aleatorio por un número aleatorio:
No es perfecto, pero es mucho más rápido que la informática
pow(2, rand()*scalefactor)
. Será "desigual" en el sentido de que la distribución será uniforme para los números dentro de un factor 2 (uniforme para 128 a 255, la mitad de la densidad para 256 a 1023, etc.).Aquí hay un histograma de la frecuencia de los números del 0 al 31 (en muestras de 1M):
fuente
rand()>>(rand()&31);
, uno intuitivamente esperaría que 1/32 de los números tengan 32 bits, y 1/32 de los números tengan 31 bits, y 1/32 de los números tengan 30 bits, etc. Pero eso es no los resultados que está obteniendo, solo aproximadamente 1/64 de los números darían como resultado 32 bits, mientras que casi la mitad debería ser 0. Dado que mis cálculos mentales no están de acuerdo con sus mediciones, tendré que hacer mis propias mediciones para calcular esto afuera.Hay exactamente el mismo número de números entre 0 y 2 ^ 29 y 2 ^ 29 y 2 ^ 30.
Otra forma de ver el problema: considere la representación binaria del número aleatorio que genera, la probabilidad de que el bit más alto sea 1 es igual a 1/2 y, por lo tanto, obtiene el orden 29 en la mitad de los casos. Lo que quiere es ver un número que esté por debajo de 2 ^ 25, pero eso significa que 5 bits más altos son todos cero, lo que ocurre con una baja probabilidad de 1/32. Lo más probable es que incluso si lo ejecutas durante mucho tiempo nunca verás el orden por debajo de 15 (la probabilidad es algo así como tirar 6 6 veces seguidas).
Ahora, la parte de tu pregunta sobre la semilla. No, la semilla no puede determinar el rango desde el que se generan los números, solo determina el primer elemento inicial. Piense en rand () como una secuencia de todos los números posibles en el rango (permutación predeterminada). La semilla determina dónde comienza a dibujar números de la secuencia. Es por eso que si desea (pseudo) aleatoriedad, usa el tiempo actual para inicializar la secuencia: no le importa que la posición desde la que comienza no esté distribuida uniformemente, lo único que importa es que nunca comience desde la misma posición.
fuente
¡Úselo
pow(2,rand())
le dará las respuestas en orden de magnitud deseada!fuente
Si desea usar números aleatorios de un servicio en línea, puede usar wget para eso, es posible que desee ver que también puede usar servicios como random.org para su generación de números aleatorios, puede atraparlos usando wget y luego leer los números de el archivo descargado
http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html
fuente