Necesito generar números aleatorios dentro de un intervalo específico, [max; min].
Además, los números aleatorios deben distribuirse uniformemente a lo largo del intervalo, no ubicarse en un punto en particular.
Actualmente estoy generando como:
for(int i=0; i<6; i++)
{
DWORD random = rand()%(max-min+1) + min;
}
A partir de mis pruebas, los números aleatorios se generan alrededor de un solo punto.
Example
min = 3604607;
max = 7654607;
Números aleatorios generados:
3631594
3609293
3630000
3628441
3636376
3621404
De las respuestas a continuación: OK, RAND_MAX es 32767. Estoy en la plataforma C ++ Windows. ¿Existe algún otro método para generar números aleatorios con una distribución uniforme?
rand()
era uniforme. ¿Qué biblioteca estás usando?cstdlib.h
'srand()
no es uniforme: cplusplus.com/reference/cstdlib/randRespuestas:
Por que
rand
es una mala ideaLa mayoría de las respuestas que obtuvo aquí utilizan la
rand
función y el operador de módulo. Es posible que ese método no genere números de manera uniforme (depende del rango y el valor deRAND_MAX
) y, por lo tanto, se desaconseja.C ++ 11 y generación en un rango
Con C ++ 11 han surgido muchas otras opciones. Uno de los cuales se adapte a sus necesidades, para generar un número aleatorio en un rango, bastante bien:
std::uniform_int_distribution
. He aquí un ejemplo:Y aquí está el ejemplo de ejecución.
Otros generadores aleatorios
El
<random>
encabezado ofrece innumerables otros generadores de números aleatorios con diferentes tipos de distribuciones, incluidos Bernoulli, Poisson y normal.¿Cómo puedo barajar un contenedor?
El estándar proporciona
std::shuffle
, que se puede utilizar de la siguiente manera:El algoritmo reordenará los elementos de forma aleatoria, con una complejidad lineal.
Boost.Random
Otra alternativa, en caso de que no tenga acceso a un compilador de C ++ 11 +, es usar Boost.Random . Su interfaz es muy similar a la de C ++ 11.
fuente
mt19937
tipo?1 9 6 2 8 7 1 4 7 7
. ¿Cómo aleatorizar esto cada vez que ejecutamos el programa?[editar] Advertencia: No lo use
rand()
para estadísticas, simulación, criptografía ni nada serio.Es lo suficientemente bueno para hacer que los números parezcan aleatorios para un humano típico con prisa, nada más.
Vea la respuesta de @ Jefffrey para obtener mejores opciones, o esta respuesta para números aleatorios seguros con cifrado.
Generalmente, los bits altos muestran una mejor distribución que los bits bajos, por lo que la forma recomendada de generar números aleatorios de un rango para propósitos simples es:
Nota : ¡asegúrese de que RAND_MAX + 1 no se desborde (gracias Demi)!
La división genera un número aleatorio en el intervalo [0, 1); "estire" esto al rango requerido. Solo cuando max-min + 1 se acerca a RAND_MAX, necesita una función "BigRand ()" como la publicada por Mark Ransom.
Esto también evita algunos problemas de división debido al módulo, lo que puede empeorar aún más sus números.
No se garantiza que el generador de números aleatorios incorporado tenga la calidad requerida para las simulaciones estadísticas. Está bien que los números "parezcan aleatorios" para un humano, pero para una aplicación seria, debe tomar algo mejor, o al menos verificar sus propiedades (la distribución uniforme suele ser buena, pero los valores tienden a correlacionarse y la secuencia es determinista ). Knuth tiene un tratado excelente (aunque difícil de leer) sobre generadores de números aleatorios, y recientemente descubrí que LFSR es excelente y muy simple de implementar, dado que sus propiedades están bien para usted.
fuente
( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min
simplemente mueva la conversión al doble y evite el problema.Me gustaría complementar las excelentes respuestas de Angry Shoe y peterchen con una breve descripción del estado del arte en 2015:
Algunas buenas elecciones
randutils
La
randutils
biblioteca (presentación) es una novedad interesante, que ofrece una interfaz simple y capacidades aleatorias robustas (declaradas). Tiene las desventajas de que agrega dependencia a su proyecto y, al ser nuevo, no se ha probado exhaustivamente. De todos modos, al ser gratis (licencia MIT) y solo de encabezado, creo que vale la pena intentarlo.Muestra mínima: una tirada de dado
Incluso si uno no está interesado en la biblioteca, el sitio web ( http://www.pcg-random.org/ ) proporciona muchos artículos interesantes sobre el tema de la generación de números aleatorios en general y la biblioteca C ++ en particular.
Boost.Random
Boost.Random
(documentación) es la biblioteca que inspiróC++11
's<random>
, con el que comparte gran parte de la interfaz. Si bien teóricamente también es una dependencia externa,Boost
ahora tiene el estado de biblioteca "cuasi estándar", y suRandom
módulo podría considerarse como la opción clásica para la generación de números aleatorios de buena calidad. Presenta dos ventajas con respecto a laC++11
solución:random_device
métodos de usos específicos del sistema a la oferta de siembra de buena calidadEl único pequeño defecto es que la oferta del módulo
random_device
no es solo de encabezado, hay que compilar y vincularboost_random
.Muestra mínima: una tirada de dado
Si bien la muestra mínima funciona bien, los programas reales deberían usar un par de mejoras:
mt19937
athread_local
: el generador es bastante voluminoso (> 2 KB) y es mejor que no se asigne en la pilamt19937
con más de un entero: el Mersenne Twister tiene un estado grande y puede beneficiarse de más entropía durante la inicializaciónAlgunas opciones no tan buenas
La biblioteca C ++ 11
Si bien es la solución más idiomática, la
<random>
biblioteca no ofrece mucho a cambio de la complejidad de su interfaz incluso para las necesidades básicas. La falla está enstd::random_device
: el Estándar no exige una calidad mínima para su salida (siempre queentropy()
devuelva0
) y, a partir de 2015, MinGW (no es el compilador más utilizado, pero no es una opción esotérica) siempre imprimirá4
en la muestra mínima.Muestra mínima: una tirada de dado
Si la implementación no está podrida, esta solución debería ser equivalente a la de Boost, y se aplican las mismas sugerencias.
La solución de Godot
Muestra mínima: una tirada de dado
Esta es una solución simple, efectiva y ordenada. Solo es un defecto, llevará un tiempo compilarlo, aproximadamente dos años, siempre que C ++ 17 se publique a tiempo y la
randint
función experimental esté aprobada en el nuevo estándar. Quizás en ese momento también mejoren las garantías sobre la calidad de la siembra.La solución peor es mejor
Muestra mínima: una tirada de dado
La antigua solución C se considera dañina y por buenas razones (consulte las otras respuestas aquí o este análisis detallado ). Aún así, tiene sus ventajas: es simple, portátil, rápido y honesto, en el sentido de que se sabe que los números aleatorios que se obtienen son poco decentes y, por lo tanto, no se tiene la tentación de usarlos para propósitos serios.
La solución de trol de contabilidad
Muestra mínima: una tirada de dado
Si bien 9 es un resultado algo inusual para una tirada de dado normal, uno tiene que admirar la excelente combinación de buenas cualidades en esta solución, que logra ser la más rápida, simple, más fácil de usar y más portátil. Sustituyendo 9 con 4, se obtiene un generador perfecto para cualquier tipo de Dungeons and Dragons dado, mientras se evitan los valores cargados de símbolos 1, 2 y 3. El único pequeño defecto es que, debido al mal genio de los trolls contables de Dilbert, este programa en realidad genera un comportamiento indefinido.
fuente
randutils
biblioteca se llama ahora PCG.Si
RAND_MAX
es 32767, puede duplicar el número de bits fácilmente.fuente
rand
llamada regresa0x1234
y la segunda0x5678
, obtienes0x12345678
. Ese es el único número que puede obtener que comienza con0x1234
, porque el próximo número siempre será0x5678
. Obtiene resultados de 32 bits, pero solo tiene 32768 números posibles.Si puede, use Boost . He tenido buena suerte con su biblioteca aleatoria .
uniform_int
debe hacer lo que quiera.fuente
uniform_int
entonces. Es bastante fácil generar una salida imparcial, ha habido varias preguntas aquí que demuestran el método.Si le preocupa la aleatoriedad y no la velocidad, debe utilizar un método seguro de generación de números aleatorios. Hay varias formas de hacer esto ... La más fácil es usar el generador de números aleatorios de OpenSSL .
También puede escribir el suyo propio utilizando un algoritmo de cifrado (como AES ). Al elegir una semilla y un IV y luego volver a cifrar continuamente la salida de la función de cifrado. Usar OpenSSL es más fácil, pero menos varonil.
fuente
Debería buscar
RAND_MAX
su compilador / entorno particular. Creo que vería estos resultados sirand()
produce un número aleatorio de 16 bits. (parece que está asumiendo que será un número de 32 bits).No puedo prometer que esta sea la respuesta, pero por favor publique su valor
RAND_MAX
y un poco más de detalles sobre su entorno.fuente
Compruebe lo que
RAND_MAX
hay en su sistema; supongo que solo tiene 16 bits y su rango es demasiado grande para ello.Más allá de eso, vea esta discusión sobre: Generación de enteros aleatorios dentro de un rango deseado y las notas sobre el uso (o no) de la función C rand () .
fuente
Este no es el código, pero esta lógica puede ayudarte.
fuente
Si desea que los números se distribuyan uniformemente en el rango, debe dividir su rango en varias secciones iguales que representen la cantidad de puntos que necesita. Luego, obtenga un número aleatorio con un mínimo / máximo para cada sección.
Como otra nota, probablemente no debería usarlo,
rand()
ya que no es muy bueno para generar números aleatorios. No sé en qué plataforma está ejecutando, pero probablemente haya una función mejor a la que pueda llamar comorandom()
.fuente
Esto debería proporcionar una distribución uniforme en el rango
[low, high)
sin usar flotadores, siempre que el rango general sea menor que RAND_MAX.y para valores superiores a RAND_MAX, desea algo como
Así es aproximadamente como std :: uniform_int_distribution hace las cosas.
fuente
Por su naturaleza, una pequeña muestra de números aleatorios no tiene que distribuirse uniformemente. Son aleatorios, después de todo. Estoy de acuerdo en que si un generador de números aleatorios está generando números que parecen estar agrupados de manera consistente, entonces probablemente haya algo mal en él.
Pero tenga en cuenta que la aleatoriedad no es necesariamente uniforme.
Editar: agregué "pequeña muestra" para aclarar.
fuente
La solución dada por man 3 rand para un número entre 1 y 10 inclusive es:
En tu caso sería:
Por supuesto, esto no es una perfecta aleatoriedad o uniformidad, como señalan otros mensajes, pero esto es suficiente para la mayoría de los casos.
fuente
@Solución
((double) rand() / (RAND_MAX+1)) * (max-min+1) + min
Advertencia : No olvide que debido al estiramiento y los posibles errores de precisión (incluso si RAND_MAX fuera lo suficientemente grande), solo podrá generar "contenedores" distribuidos uniformemente y no todos los números en [min, max].
@Solución: Bigrand
Advertencia : Tenga en cuenta que esto duplica los bits, pero aún así no podrá generar todos los números en su rango en general, es decir, no es necesariamente cierto que BigRand () generará todos los números en su rango.
Información : Su enfoque (módulo) es "correcto" siempre que el rango de rand () exceda su rango de intervalo y rand () sea "uniforme". El error para como máximo los primeros números máximo - mínimo es 1 / (RAND_MAX +1).
Además, sugiero cambiar también al nuevo paquete aleatorio e en C ++ 11, que ofrece mejores y más variedades de implementaciones que rand ().
fuente
Esta es la solución que se me ocurrió:
Esta es una solución de cubo, conceptualmente similar a las soluciones que se utilizan
rand() / RAND_MAX
para obtener un rango de punto flotante entre 0-1 y luego redondearlo en un cubo. Sin embargo, utiliza matemática puramente entera y aprovecha el piso de división de enteros para redondear el valor al cubo más cercano.Hace algunas suposiciones. Primero, asume que
RAND_MAX * (max - min + 1)
siempre encajará dentro de unint32_t
. SiRAND_MAX
es 32767 y se utilizan cálculos de 32 bits int, el rango máximo que puede tener es 32767. Si su implementación tiene un RAND_MAX mucho más grande, puede superar esto usando un entero más grande (comoint64_t
) para el cálculo. En segundo lugar, siint64_t
se usa peroRAND_MAX
sigue siendo 32767, en rangos mayores queRAND_MAX
usted comenzará a tener "huecos" en los números de salida posibles. Este es probablemente el mayor problema con cualquier solución derivada del escaladorand()
.Sin embargo, las pruebas sobre una gran cantidad de iteraciones muestran que este método es muy uniforme para rangos pequeños. Sin embargo, es posible (y probable) que matemáticamente esto tenga un pequeño sesgo y posiblemente desarrolle problemas cuando se acerque el rango
RAND_MAX
. Pruébelo usted mismo y decida si satisface sus necesidades.fuente
Por supuesto, el siguiente código no le dará números aleatorios sino números pseudoaleatorios. Usa el siguiente código
Por ejemplo:
Debes llamar
de lo contrario, los números no serán casi aleatorios.
fuente
Acabo de encontrar esto en Internet. Esto debería funcionar:
fuente