C ++ generando números aleatorios

Mi salida es de 20 aleatorios, no entre 10 y 1, ¿alguien puede explicar por qué sucede esto?

#include  #include  #include  using namespace std; int main() { srand((unsigned)time(0)); int random_integer; int lowest=1, highest=10; int range=(highest-lowest)+1; for(int index=0; index<20; index++){ random_integer = lowest+int(range*rand()/(RAND_MAX + 1.0)); cout << random_integer << endl; } } 

salida: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Porque, en su plataforma, RAND_MAX == INT_MAX .

El range*rand() expresión range*rand() nunca puede tomar un valor mayor que INT_MAX . Si la expresión matemática es mayor que INT_MAX , el desbordamiento entero la reduce a un número entre INT_MIN e INT_MAX . Dividir eso por RAND_MAX siempre rendirá cero.

Prueba esta expresión:

 random_integer = lowest+int(range*(rand()/(RAND_MAX + 1.0))) 

Es mucho más fácil usar la biblioteca correctamente que rand (suponiendo que está lo suficientemente familiarizado con C ++ que la syntax no lo arroja).

 #include  #include  int main() { std::random_device r; std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; std::mt19937 eng(seed); std::uniform_int_distribution<> dist(1, 10); for(int i = 0; i < 20; ++i) std::cout << dist(eng) << " "; } 
 random_integer = (rand() % 10) + 1 

Eso debería darte un número pseudoaleatorio entre 1 y 10.

Una respuesta algo tardía, pero debería proporcionar cierta información adicional si la calidad de la generación es importante. (No todas las aplicaciones necesitan esto, un pequeño sesgo a menudo no es un problema).

Primero, por supuesto, el problema en el código original es el hecho de que range * rand() tiene precedencia sobre la siguiente división, y se hace usando aritmética de enteros. Dependiendo de RAND_MAX , esto puede resultar fácilmente en un desbordamiento, con resultados definidos por la implementación; en todas las implementaciones que sé, si se produce un desbordamiento (porque RAND_MAX > INT_MAX / range , los resultados reales serán casi con seguridad menores que RAND_MAX + 1.0 , y la división dará como resultado un valor inferior a 1.0 . Hay varias formas de evitar esto: el más simple y más confiable es simplemente rand() % range + lowest .

Tenga en cuenta que esto supone que rand() es de calidad razonable. Muchas implementaciones anteriores no lo fueron, y he visto al menos uno donde rand() % 6 + 1 para simular un lanzamiento de dados alterno impar y par. La única solución correcta aquí es obtener una mejor implementación de rand() ; ha llevado a personas que intentan soluciones alternativas, como (range * (rand() / (RAND_MAX + 1.0))) + lowest . Esto enmascara el problema, pero no cambiará a un generador malo en uno bueno.

Un segundo problema, si la calidad de la generación es importante, es que al generar enteros aleatorios, discretizas: si estás simulando el lanzamiento de un dado, por ejemplo, tienes seis valores posibles, que quieres que ocurran con la misma probabilidad. El generador aleatorio generará RAND_MAX + 1 valores diferentes, con la misma probabilidad. Si RAND_MAX + 1 no es un múltiplo de 6, no hay forma posible de distribuir los valores iguales entre los 6 valores deseados. Imagine el caso simple donde RAND_MAX + 1 es 10. Utilizando el método % anterior, los valores 1-4 son dos veces más probables que los valores 5 y 6. Si usa la fórmula más complicada 1 + int(6 * (rand() / (RAND_MAX + 1.0))) (en el caso donde RAND_MAX + 1 == 10 , resulta que 3 y 6 son solo la mitad de probabilidades que los otros valores. Matemáticamente, simplemente no hay manera de distribuir 10 valores diferentes en 6 ranuras con la misma cantidad de elementos en cada ranura.

Por supuesto, RAND_MAX siempre será considerablemente mayor que 10, y el sesgo introducido será considerablemente menor; si el rango es significativamente menor que RAND_MAX , podría ser aceptable. Si no lo es, sin embargo, el procedimiento habitual es algo así como:

 int limit = (RAND_MAX + 1LL) - (RAND_MAX + 1LL) % range; // 1LL will prevent overflow on most machines. int result = rand(); while ( result >= limit ) { result = rand(); } return result % range + lowest; 

(Hay varias formas de determinar los valores que hay que descartar. Este es el que uso, pero recuerdo que Andy Koenig usó algo completamente diferente, pero que al final arrojó los mismos valores).

Tenga en cuenta que la mayoría de las veces, no ingresará el ciclo; el peor caso es cuando el range es (RAND_MAX + 1) / 2 + 1 , en cuyo caso, aún promediará menos de una vez a través del ciclo.

Tenga en cuenta que estos comentarios solo se aplican cuando necesita una cantidad fija de resultados discretos. Para el (otro) caso común de generar un número de punto flotante aleatorio en el rango de [0,1) , rand() / (RAND_MAX + 1.0) es casi tan bueno como lo que obtendrás.

Visual Studio 2008 no tiene ningún problema con ese progtwig en absoluto y felizmente genera una franja de números aleatorios.

Lo que tendría cuidado es el / (RAND_MAX +1.0) ya que es probable que caiga en problemas enteros y termine con un gran cero.

Transmite al doble antes de dividir y luego regresa a int después

Sugiero que reemplace rand()/(RAND_MAX + 1.0) con un range*double(rand())/(RAND_MAX + 1.0)) . Dado que mi solución parece dar dolores de cabeza …

posibles combinaciones de argumentos:

  • range*rand() es un entero y se desborda.
  • double(range*rand()) desborda antes de convertirlo a doble.
  • range*double(rand()) no se desborda y arroja los resultados esperados.

Mi publicación original tenía dos llaves, pero no cambiaron nada (los resultados son los mismos).

 (rand() % highest) + lowest + 1 

Probablemente “10 * rand ()” sea más pequeño que “RAND_MAX + 1.0”, por lo que el valor de su cálculo es 0.

Está generando un número aleatorio (es decir, (range*rand()/(RAND_MAX + 1.0)) ) cuyo valor está entre -1 y 1 ( ]-1,1[ ) y luego lo convierte en un número entero. El valor entero de tal número es siempre 0, por lo que terminas con el valor lower + 0

EDITAR: agregué la fórmula para aclarar mi respuesta

Es una de las lógicas más simples, lo obtuve de un blog. en esta lógica, puedes limitar los números aleatorios con ese operador de módulo dado (%) dentro del ciclo for, es solo un copoy y pegar desde ese blog, pero de cualquier forma compruébalo:

 // random numbers generation in C++ using builtin functions #include  using namespace std; #include  using std::setw; #include  // contains function prototype for rand int main() { // loop 20 times for ( int counter = 1; counter <= 20; counter++ ) { // pick random number from 1 to 6 and output it cout << setw( 10 ) << ( 1 + rand() % 6 ); // if counter divisible by 5, begin new line of output if ( counter % 5 == 0 ) cout << endl; } return 0; // indicates successful termination } // end main 

- Ver más en: http://www.programmingtunes.com/generation-of-random-numbers-c/#sthash.BTZoT5ot.dpuf

¿Qué pasa con el uso de una condición para verificar si el último número es el mismo que el actual? Si se cumple la condición, genere otro número aleatorio. Esta solución funciona, pero tomará más tiempo sin embargo.