rango randomize numeros negativos generar funcion dev decimales arreglo aleatorios c++ random floating-point

randomize - Generación de números flotantes aleatorios de C++



generar numeros aleatorios negativos en c++ (14)

C ++ 11 te da muchas nuevas opciones al random . El documento canónico sobre este tema sería N3551, Generación de números aleatorios en C ++ 11

Para ver por qué el uso de rand() puede ser problemático, vea el material de presentación channel9.msdn.com/Events/GoingNative/2013/… por Stephan T. Lavavej dado durante el evento GoingNative 2013 . Las diapositivas están en los comentarios, pero aquí hay un enlace directo .

También cubro boost y el uso de rand ya que el código heredado aún puede requerir su soporte.

El siguiente ejemplo se extrae del sitio cppreference y utiliza el motor std::uniform_real_distribution y el std::uniform_real_distribution que genera números en el intervalo [0,10) , con otros motores y distribuciones comentadas ( véalo en vivo ):

#include <iostream> #include <iomanip> #include <string> #include <map> #include <random> int main() { std::random_device rd; // // Engines // std::mt19937 e2(rd()); //std::knuth_b e2(rd()); //std::default_random_engine e2(rd()) ; // // Distribtuions // std::uniform_real_distribution<> dist(0, 10); //std::normal_distribution<> dist(2, 2); //std::student_t_distribution<> dist(5); //std::poisson_distribution<> dist(2); //std::extreme_value_distribution<> dist(0,2); std::map<int, int> hist; for (int n = 0; n < 10000; ++n) { ++hist[std::floor(dist(e2))]; } for (auto p : hist) { std::cout << std::fixed << std::setprecision(1) << std::setw(2) << p.first << '' '' << std::string(p.second/200, ''*'') << ''/n''; } }

La salida será similar a la siguiente:

0 **** 1 **** 2 **** 3 **** 4 ***** 5 **** 6 ***** 7 **** 8 ***** 9 ****

La salida variará dependiendo de la distribución que elija, por lo que si decidimos ir con std::normal_distribution con un valor de 2 para la media y el estándar ( por ejemplo, dist(2, 2) lugar de la salida sería similar a esta) vivir ):

-6 -5 -4 -3 -2 ** -1 **** 0 ******* 1 ********* 2 ********* 3 ******* 4 **** 5 ** 6 7 8 9

La siguiente es una versión modificada de algunos de los códigos presentados en N3551 ( N3551 en vivo ):

#include <algorithm> #include <array> #include <iostream> #include <random> std::default_random_engine & global_urng( ) { static std::default_random_engine u{}; return u ; } void randomize( ) { static std::random_device rd{}; global_urng().seed( rd() ); } int main( ) { // Manufacture a deck of cards: using card = int; std::array<card,52> deck{}; std::iota(deck.begin(), deck.end(), 0); randomize( ) ; std::shuffle(deck.begin(), deck.end(), global_urng()); // Display each card in the shuffled deck: auto suit = []( card c ) { return "SHDC"[c / 13]; }; auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; }; for( card c : deck ) std::cout << '' '' << rank(c) << suit(c); std::cout << std::endl; }

Los resultados se verán similares a:

5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S

Aumentar

Por supuesto, Boost.Random es una opción, aquí estoy usando boost::random::uniform_real_distribution :

#include <iostream> #include <iomanip> #include <string> #include <map> #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_real_distribution.hpp> int main() { boost::random::mt19937 gen; boost::random::uniform_real_distribution<> dist(0, 10); std::map<int, int> hist; for (int n = 0; n < 10000; ++n) { ++hist[std::floor(dist(gen))]; } for (auto p : hist) { std::cout << std::fixed << std::setprecision(1) << std::setw(2) << p.first << '' '' << std::string(p.second/200, ''*'') << ''/n''; } }

rand ()

Si debe usar rand() , podemos ir a la sección de Preguntas frecuentes de C para obtener guías sobre ¿Cómo puedo generar números aleatorios de punto flotante? , que básicamente da un ejemplo similar a este para generar un intervalo en [0,1) :

#include <stdlib.h> double randZeroToOne() { return rand() / (RAND_MAX + 1.); }

y para generar un número aleatorio en el rango de [M,N) :

double randMToN(double M, double N) { return M + (rand() / ( RAND_MAX / (N-M) ) ) ; }

¿Cómo genero flotadores aleatorios en C ++?

Pensé que podría tomar el rand entero y dividirlo por algo, ¿sería eso suficiente?


Echa un vistazo a Boost.Random . Podrías hacer algo como esto:

float gen_random_float(float min, float max) { boost::mt19937 rng; boost::uniform_real<float> u(min, max); boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u); return gen(); }

Si juegas, podrías hacerlo mejor pasando el mismo objeto mt19937 en lugar de construir uno nuevo cada vez, pero espero que tengas la idea.


El número flotante válido completamente aleatorio se genera de la siguiente manera: signo aleatorio, exponente aleatorio y mantisa aleatoria. Este es un ejemplo de la generación de números aleatorios desde 0..MAXFLOAT con distribución uniforme:

static float frand(){ float f; UINT32 *fi = (UINT32*)&f; *fi = 0; const int minBitsRandGives = (1<<15); // RAND_MAX is at least (1<<15) UINT32 randExp = (rand()%254)+1; // Exponents are in range of [1..254] UINT32 randMantissa = ((rand() % minBitsRandGives) << 8) | (rand()%256); *fi = randMantissa | (randExp<<23); // Build a float with random exponent and random mantissa return f; }

Nota importante: RAND_MAX es por defecto igual a 2 ^ 16 (en sistemas de 32 bits), por lo que rand () puede generar como máximo 15 bits aleatorios. Como el punto flotante tiene un total de 32 bits, debemos activar el rand () al menos 3 veces para generar 32 bits aleatorios. Utilicé 8 bits de rand () para generar Exponent y otras 2 llamadas a rand () para generar 23 bits de mantisa.

Error común que se debe evitar: Si usa (float)rand()/MAX_RAND para obtener un punto flotante en el rango [0..1], seguirá obteniendo números aleatorios en una distribución uniforme pero de baja precisión . Por ejemplo, su generador aleatorio puede generar 0.00001 y 0.00002 pero no puede generar 0.000017. Tal aleatoriedad es 256 veces menos precisa que la representación de punto flotante real.

Optimización: Mi función no está optimizada para la velocidad. Puede mejorarlo reemplazando la división ''%'' con operaciones lógicas a nivel de bits. Por ejemplo, en lugar de %256 use &0xFF


En c++ moderno puede usar el encabezado <random> que viene con c++11 .
Para obtener float aleatorios puede usar std::uniform_real_distribution<> .

Puede usar una función para generar los números y, si no desea que los números sean iguales todo el tiempo, configure el motor y la distribución para que sean static .
Ejemplo:

float get_random() { static std::default_random_engine e; static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1 return dis(e); }

Es ideal para colocar el float en un contenedor como std::vector :

int main() { std::vector<float> nums; for (int i{}; i != 5; ++i) // Generate 5 random floats nums.emplace_back(get_random()); for (const auto& i : nums) std::cout << i << " "; }

Ejemplo de salida:

0.0518757 0.969106 0.0985112 0.0895674 0.895542


En algunos sistemas (Windows con VC viene a la mente, actualmente), RAND_MAX es ridículamente pequeño, i. mi. Sólo 15 bits. Al dividir por RAND_MAX solo está generando una mantisa de 15 bits en lugar de los 23 bits posibles. Esto puede o no ser un problema para usted, pero se están perdiendo algunos valores en ese caso.

Oh, solo noté que ya había un comentario para ese problema. De todos modos, aquí hay un código que podría resolver esto por ti:

float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);

No probado, pero podría funcionar :-)


En mi opinión, la respuesta anterior proporciona un flotador "aleatorio", pero ninguno de ellos es realmente un flotador aleatorio (es decir, se pierde una parte de la representación del flotador). Antes de apurarme a mi implementación, veamos primero el formato estándar ANSI / IEEE para flotadores:

| signo (1 bit) | e (8 bits) | f (23 bits) |

el número representado por esta palabra es (-1 * signo) * 2 ^ e * 1.f

tenga en cuenta que el número ''e'' es un número sesgado (con un sesgo de 127) que varía de -127 a 126. La función más simple (y en realidad la más aleatoria) es escribir los datos de un int aleatorio en un flotador, así

int tmp = rand(); float f = (float)*((float*)&tmp);

tenga en cuenta que si hace float f = (float)rand(); convertirá el número entero en un flotador (por lo tanto, 10 se convertirá en 10.0).

Así que ahora, si desea limitar el valor máximo, puede hacer algo como (no estoy seguro de si esto funciona)

int tmp = rand(); float f = *((float*)&tmp); tmp = (unsigned int)f // note float to int conversion! tmp %= max_number; f -= tmp;

pero si observa la estructura del flotador, puede ver que el valor máximo de un flotador es (aprox.) 2 ^ 127, que es mucho más grande que el valor máximo de un int (2 ^ 32), por lo que se descarta una parte significativa de Los números que pueden ser representados por un flotador. Esta es mi implementación final:

/** * Function generates a random float using the upper_bound float to determine * the upper bound for the exponent and for the fractional part. * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127) * @param max_exp sets the maximum number to 2 * e^max_exp (max 126) * @param sign_flag if sign_flag = 0 the random number is always positive, if * sign_flag = 1 then the sign bit is random as well * @return a random float */ float randf(int min_exp, int max_exp, char sign_flag) { assert(min_exp <= max_exp); int min_exp_mod = min_exp + 126; int sign_mod = sign_flag + 1; int frac_mod = (1 << 23); int s = rand() % sign_mod; // note x % 1 = 0 int e = (rand() % max_exp) + min_exp_mod; int f = rand() % frac_mod; int tmp = (s << 31) | (e << 23) | f; float r = (float)*((float*)(&tmp)); /** uncomment if you want to see the structure of the float. */ // printf("%x, %x, %x, %x, %f/n", (s << 31), (e << 23), f, tmp, r); return r; }

El uso de esta función randf(0, 8, 0) devolverá un número aleatorio entre 0.0 y 255.0


Llame al código con dos valores float , el código funciona en cualquier rango.

float rand_FloatRange(float a, float b) { return ((b - a) * ((float)rand() / RAND_MAX)) + a; }


No estaba satisfecho con ninguna de las respuestas hasta ahora, así que escribí una nueva función de flotación aleatoria. Hace suposiciones a nivel de bits sobre el tipo de datos flotante. Todavía necesita una función rand () con al menos 15 bits aleatorios.

//Returns a random number in the range [0.0f, 1.0f). Every //bit of the mantissa is randomized. float rnd(void){ //Generate a random number in the range [0.5f, 1.0f). unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand())); unsigned short coinFlips; //If the coin is tails, return the number, otherwise //divide the random number by two by decrementing the //exponent and keep going. The exponent starts at 63. //Each loop represents 15 random bits, a.k.a. ''coin flips''. #define RND_INNER_LOOP() / if( coinFlips & 1 ) break; / coinFlips >>= 1; / ret -= 0x800000 for(;;){ coinFlips = rand(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); //At this point, the exponent is 60, 45, 30, 15, or 0. //If the exponent is 0, then the number equals 0.0f. if( ! (ret & 0x3F800000) ) return 0.0f; RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP(); } return *((float *)(&ret)); }


Para C ++, puede generar números flotantes reales dentro del rango especificado por la variable dist

#include <random> //If it doesnt work then use #include <tr1/random> #include <iostream> using namespace std; typedef std::tr1::ranlux64_base_01 Myeng; typedef std::tr1::normal_distribution<double> Mydist; int main() { Myeng eng; eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970); Mydist dist(1,10); dist.reset(); // discard any cached values for (int i = 0; i < 10; i++) { std::cout << "a random value == " << (int)dist(eng) << std::endl; } return (0); }


Si está utilizando C ++ y no C, recuerde que en el informe técnico 1 (TR1) y en el borrador de C ++ 0x se han agregado facilidades para un generador de números aleatorios en el archivo de encabezado, creo que es idéntico al Boost. Biblioteca aleatoria y definitivamente más flexible y "moderna" que la función de biblioteca C, rand.

Esta sintaxis ofrece la posibilidad de elegir un generador (como mersenne twister mt19937) y luego elegir una distribución (normal, bernoulli, binomial, etc.).

La sintaxis es la siguiente (descarada de este sitio ):

#include <iostream> #include <random> ... std::tr1::mt19937 eng; // a core engine class std::tr1::normal_distribution<float> dist; for (int i = 0; i < 10; ++i) std::cout << dist(eng) << std::endl;


Si sabe que su formato de punto flotante es IEEE 754 (casi todas las CPU modernas, incluidas Intel y ARM), puede crear un número de punto flotante aleatorio a partir de un entero aleatorio utilizando métodos de bit-bit. Esto solo se debe tener en cuenta si no tiene acceso a C ++ 11''s random o Boost.Random que son mucho mejores.

float rand_float() { // returns a random value in the range [0.0-1.0) // start with a bit pattern equating to 1.0 uint32_t pattern = 0x3f800000; // get 23 bits of random integer uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand()); // replace the mantissa, resulting in a number [1.0-2.0) pattern |= random23; // convert from int to float without undefined behavior assert(sizeof(float) == sizeof(uint32_t)); char buffer[sizeof(float)]; memcpy(buffer, &pattern, sizeof(float)); float f; memcpy(&f, buffer, sizeof(float)); return f - 1.0; }

Esto dará una mejor distribución que una división de uso.


rand () devuelve un int entre 0 y RAND_MAX. Para obtener un número aleatorio entre 0.0 y 1.0, primero convierta el retorno int por rand () a un flotador, luego divídalo por RAND_MAX.


drand48(3) es la forma estándar POSIX. GLibC también proporciona una versión reentrante, drand48_r(3) .

La función se declaró obsoleta en SVID 3, pero no se proporcionó una alternativa adecuada, por lo que IEEE Std 1003.1-2013 aún la incluye y no tiene notas de que vaya a alguna parte pronto.

En Windows, la forma estándar es CryptGenRandom() .


rand() puede usarse para generar números pseudoaleatorios en C ++. En combinación con RAND_MAX y un poco de matemáticas, puede generar números aleatorios en cualquier intervalo arbitrario que elija. Esto es suficiente para propósitos de aprendizaje y programas de juguetes. Si necesita números verdaderamente aleatorios con distribución normal, deberá emplear un método más avanzado.

Esto generará un número de 0.0 a 1.0, inclusive.

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

Esto generará un número de 0.0 a un float arbitrario, X :

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

Esto generará un número de un LO arbitrario a otro HI arbitrario:

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

Tenga en cuenta que la función rand() a menudo no será suficiente si necesita números verdaderamente aleatorios.

Antes de llamar a rand() , primero debe "inicializar" el generador de números aleatorios llamando a srand() . Esto se debe hacer una vez durante la ejecución de su programa, no una vez cada vez que llama a rand() . Esto se hace a menudo así:

srand (static_cast <unsigned> (time(0)));

Para llamar a rand o srand debes #include <cstdlib> .

Para llamar al time , debes #include <ctime> .