152 votos

Generación de números aleatorios flotador C++

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

¿Pensé que podría tomar al entero rand y dividirlo por algo, eso sería lo suficientemente adecuado?

232voto

John Dibling Puntos 56814

rand() puede ser utilizado para generar psudo-números aleatorios en C++. En combinación con RAND_MAX y un poco de matemáticas, puede generar números aleatorios en cualquier intervalo de tiempo que usted elija. Esto es suficiente para los propósitos de aprendizaje y los juguetes de los programas. Si usted necesita de verdad , los números aleatorios con distribución normal, entonces usted necesitará 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 va a generar un número entre 0.0 y arbitraria float, X:

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

Esto generará un número de arbitraria LO para arbitraria HI:

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

Tenga en cuenta que el rand() función no suele ser suficiente, si usted necesita números verdaderamente aleatorios.


Antes de llamar a rand(), usted primero debe "sembrar" el generador de números aleatorios llamando srand(). Esto debe ser realizado una vez durante su programa de correr, no cada vez que se llame rand(). Esto se hace a menudo como este:

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

En fin llame rand o srand debe #include <cstdlib>.

En fin llame time, deberá #include <ctime>.

54voto

rlbond Puntos 24215

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();
}

Jugar, puede hacer mejor pasando el objeto mismo del mt19937 alrededor en vez de construir una nueva cada vez, pero espero que usted consigue la idea.

53voto

Shafik Yaghmour Puntos 42198

C++11 le da un montón de nuevas opciones con random.

A ver por qué el uso de rand() puede ser problemático ver el rand() Considera Perjudicial el material de la presentación por Stephan T. Lavavej dado durante el GoingNative 2013 evento. Las diapositivas están en los comentarios, pero aquí hay un enlace directo.

El ejemplo de abajo es el destilado de la anterior documento y utiliza el std::mersenne_twister_engine motor y el std::uniform_real_distribution que genera los números en la [0,10) intervalo, con otros motores y distribuciones comentado (ver 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 va a variar dependiendo de la distribución que elija, así que si nos decidimos a ir con std::normal_distribution<> dist(2, 2); en lugar de std::uniform_real_distribution<> dist(0, 10); el resultado sería similar a este:

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

Boost

Por supuesto Boost.Random siempre es una opción, así que, aquí estoy usando boost::azar::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 usted debe usar rand() luego podemos ir a la C FAQ para guías sobre ¿Cómo puedo generar de punto flotante de números aleatorios? que, básicamente, nos da un ejemplo similar a este para la generación de una en el intervalo [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) ) ) ;  
}

20voto

ГошУ Puntos 6799

el código con dos valores flotantes, el código funciona en cualquier rango.

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

17voto

Rick Puntos 2477

Si usted está utilizando C++ y no en C, a continuación, recordar que en el informe técnico 1 (TR1) y en el C++0x proyecto se han añadido en las instalaciones de un generador de números aleatorios en el archivo de encabezado, yo creo que es idéntica a la Boost.Random de la biblioteca y, definitivamente, más flexible y con "moderna" de la biblioteca de C de la función, rand.

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

La sintaxis es como sigue (desvergonzado prestados desde este sitio web):

  #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;

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X