Pregunta

El siguiente código genera un número aleatorio cada segundo:

int main ()
{
    srand(time(NULL)); // Seeds number generator with execution time.

    while (true)
    {
        int rawRand = rand();

        std::cout << rawRand << std::endl;

        sleep(1);
    }
}

¿Cómo puede dimensionar estos números para que estén siempre en el rango de 0-100?

¿Fue útil?

Solución

Si está utilizando C ++ y se preocupan por una buena distribución puede utilizar TR1 C ++ 11 <random>.

#include <random>

std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]

std::cout << idist(rgen) << std::endl;

Otros consejos

Todos los ejemplos publicado hasta ahora en realidad dar resultados mal distribuidos. Ejecutar el código menudo y crear una estadística para ver cómo los valores se convierten sesgada.

Una mejor manera de generar una real uniforme distribución de números aleatorios en cualquier rango [0, N ] es la siguiente (suponiendo que rand realidad sigue una distribución uniforme, el cual está lejos de ser evidente):

unsigned result;
do {
    result = rand();
} while (result > N);

Por supuesto, ese método es lento pero no producir una distribución buena. Una forma un poco más inteligente de hacer esto es encontrar el mayor múltiplo de N que es más pequeño que RAND_MAX y usar eso como el límite superior. Después de eso, se puede tomar el result % (N + 1) con seguridad.

Para obtener una explicación ¿Por qué el método módulo ingenua es malo y por qué lo anterior es mejor, consulte excelente artículo de Julienne en usando rand .

int rawRand = rand() % 101;

Sede (para más detalles):

rand - C ++ Referencia

Otros también han señalado que esto no se va a dar la mejor distribución de los números aleatorios posibles. Si ese tipo de cosas es importante en su código, usted tiene que hacer:

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

Editar

Tres años después, estoy haciendo una edición. Como han mencionado otros, rand() tiene una gran cantidad de problemas. Obviamente, no puedo recomendar su uso cuando hay mejores alternativas de cara al futuro. Usted puede leer todo acerca de los detalles y recomendaciones aquí:

rand () consideran perjudiciales | GoingNative 2013

Puede hacer

cout << rawRand % 100 << endl; // Outputs between 0 and 99

cout << rawRand % 101 << endl; // outputs between 0 and 100

Para la gente downvoting; observar un minuto después de esto fue Iniciado Salí del comentario:

http://www.cplusplus.com/reference/clibrary/cstdlib/rand "Aviso sin embargo, que esta operación módulo no genera un número aleatorio verdaderamente distribuida uniformemente en el lapso (ya que en la mayoría de los casos disminuyen los números son ligeramente más probable), pero por lo general es una buena aproximación para distancias cortas."

Con enteros de 64 bits y el uso de 100 números como de salida, los números 0-16 se representan con 1,00000000000000000455% de los números (una precisión con respecto a distribuye de forma idéntica de 1% en aproximadamente 10 -18 ), mientras que los números 17-99 se representan con 0.99999999999999999913% de los números. Sí, no perfectamente distribuido, pero una muy buena aproximación para los pequeños tramos.

Tenga en cuenta también, en qué pide el OP para los números idénticamente distribuidas? Por lo que sabemos se están utilizando para fines donde un pequeño desviaciones no importa (por ejemplo, distintas de la criptografía nada - y si están utilizando los números para la criptografía esta pregunta es demasiado ingenua para que sean escribiendo su propia criptografía ).

Editar - Para las personas que se preocupan verdaderamente por tener una distribución uniforme de números aleatorios las siguientes obras de código. Tenga en cuenta que esto no es necesariamente óptima al igual que con 64 bits enteros al azar, se requerirá de dos llamadas de rand() una vez cada 10 ^ 18 llamadas.

unsigned N = 100; // want numbers 0-99
unsigned long randTruncation = (RAND_MAX / N) * N; 
// include every number the N times by ensuring rawRand is between 0 and randTruncation - 1 or regenerate.
unsigned long rawRand = rand();

while (rawRand >= randTruncation) {
    rawRand = rand();  
// with 64-bit int and range of 0-99 will need to generate two random numbers
// about 1 in every (2^63)/16 ~ 10^18 times (1 million million times)

// with 32-bit int and range of 0-99 will need to generate two random numbers 
// once every 46 million times.

}
cout << rawRand % N << stdl::endl;

Ver man 3 rand -. Necesita a escala dividiendo por RAND_MAX para obtener el rango [0, 1] después de lo cual se puede multiplicar por 100 para su rango objetivo

Para el rango min a max (inclusive), uso: int result = rand() % (max - min + 1) + min;

¿Cuánto tiempo una respuesta le gustaría tener.

el más simple es la de convertir usando el resto cuando se divide por 101:

int value = rawRand % 101;

A semipurist sería cambiar la escala utilizando dobles:

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5

Y un purista diría que Rand no produce números aleatorios.

Para su información, la calidad de números aleatorios se mide tomando una secuencia de números y luego calcular la probabilidad matemática de que la fuente de esa secuencia fue al azar. El simple truco usando el resto es una elección muy pobre si usted está después de la aleatoriedad.

Algunas personas han publicado el siguiente código de ejemplo:

int rawRand = (rand() / RAND_MAX) * 100;

Esta es una forma no válida de resolver el problema, ya que ambos rand () y RAND_MAX son números enteros. En C ++, esto resulta en la división integral, que truncará los resultados decimal puntos. Como RAND_MAX> = rand (), el resultado de esta operación es 1 o 0, lo que significa rawRand sólo puede ser 0 o 100. Una correcta forma de hacer esto sería la siguiente:

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;

Dado que uno de los operandos ahora se se utiliza una, la división doble punto flotante, que volvería un valor adecuado entre 0 y 1.

rawRand% 101 daría [0-100], inclusive.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top