¿Cómo genero flotantes aleatorios en C ++?
Pensé que podría tomar el rand entero y dividirlo por algo, ¿sería suficiente?
c++
random
floating-point
Hasen
fuente
fuente
random
encabezado agregado en C ++ 11 se ve reforzada por el documento estándar N3924: Desalentador rand () en C ++ 14 . Incluyorand()
en mi respuesta por consideraciones principalmente históricas, pero también me doy cuenta de que existen aplicaciones heredadas.<random>
encabezadoRespuestas:
rand()
se puede usar para generar números pseudoaleatorios en C ++. En combinación conRAND_MAX
un poco de matemática, puede generar números aleatorios en cualquier intervalo arbitrario que elija. Esto es suficiente para fines 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.
Esto generará un número desde 0,0 hasta cierto arbitraria
float
,X
:Esto generará un número de algún arbitrario
LO
a otro arbitrarioHI
:Tenga en cuenta que la
rand()
función a menudo no será suficiente si necesita números verdaderamente aleatorios.Antes de llamar
rand()
, primero debe "inicializar" el generador de números aleatorios llamandosrand()
. Esto debe hacerse una vez durante la ejecución de su programa, no una vez cada vez que llamerand()
. Esto a menudo se hace así:Para llamar
rand
osrand
debes hacerlo#include <cstdlib>
.Para llamar
time
, debes hacerlo#include <ctime>
.fuente
rand()
. Esta pregunta, y mi respuesta, se centró específicamente en aprender lo básico y no le preocupaban los altos grados de precisión. Tienes que aprender a caminar antes de poder aprender a correr.C ++ 11 le ofrece muchas opciones nuevas con
random
. El artículo canónico sobre este tema sería N3551, Generación de números aleatorios en C ++ 11Para ver por qué usar
rand()
puede ser problemático, consulte el material de presentación rand () considerado perjudicial 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 utilizo,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 :: mersenne_twister_engine y el std :: uniform_real_distribution que genera números en el
[0,10)
intervalo, con otros motores y distribuciones comentadas a cabo ( ver en directo ):la salida será similar a la siguiente:
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
tanto para media y STDDEV por ejemplo,dist(2, 2)
en lugar de la salida sería similar a esta ( ver en directo ):La siguiente es una versión modificada de algunos de los códigos presentados en
N3551
( ver en vivo ):Los resultados serán similares a:
Aumentar
Por supuesto, Boost.Random también es siempre una opción, aquí estoy usando boost :: random :: uniform_real_distribution :
rand ()
Si debe usarlo
rand()
, podemos ir a las Preguntas frecuentes de C para obtener una guía sobre ¿Cómo puedo generar números aleatorios de punto flotante? , que básicamente da un ejemplo similar a este para generar un intervalo[0,1)
:y para generar un número aleatorio en el rango de
[M,N)
:fuente
randMToN
pls? tenga en cuenta que es[M,N]
o agregue de nuevo el+ 1.
de lo anteriorrandZeroToOne
. -> piensa en llamarlo así:randMToN(0.0, 1.0);
(N-M)
. Aquí se encuentra una buena manera de lidiar con este error: stackoverflow.com/questions/33058848/…Echa un vistazo a Boost.Random . Podrías hacer algo como esto:
Juega un poco, es mejor que pases el mismo objeto mt19937 en lugar de construir uno nuevo cada vez, pero espero que entiendas la idea.
fuente
max
, pero puede utilizar una participación abiertamin
, puede invertir el intervalo fácilmente:return min + max - gen();
.En moderno
c++
, puede usar el<random>
encabezado que viene conc++11
.Para obtener aleatorios
float
, puedes usarstd::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
static
.Ejemplo:
Es ideal para colocar el
float
's en un contenedor comostd::vector
:Salida de ejemplo:
fuente
std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
es técnicamente incorrecto, nunca se generará 1.0, consulte en.cppreference.com/w/cpp/numeric/random/…To create a distribution over the closed interval [a,b], std::nextafter(b, std::numeric_limits<RealType>::max()) may be used as the second parameter.
Llame al código con dos
float
valores, el código funciona en cualquier rango.fuente
fmaf()
(o lafma()
sobrecarga flotante en C ++) en C99 o C ++ 11, lo que podría preservar más precisión. Como enfmaf((float)rand() / RAND_MAX, b - a, a)
.Si está utilizando C ++ y no C, recuerde que en el informe técnico 1 (TR1) y en el borrador de C ++ 0x han agregado funciones 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 el mersenne twister mersenne mt19937) y luego elegir una distribución (normal, bernoulli, binomial, etc.).
La sintaxis es la siguiente (descaradamente prestado de este sitio ):
fuente
En algunos sistemas (Windows con VC me
RAND_MAX
viene a la mente, actualmente), es ridículamente pequeño, i. mi. solo 15 bit. Al dividir porRAND_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 está perdiendo algunos valores en ese caso.Oh, acabo de notar que ya había un comentario para ese problema. De todos modos, aquí hay un código que podría resolver esto por usted:
No probado, pero podría funcionar :-)
fuente
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 todavía la incluye y no tiene notas de que vaya a ir a ninguna parte pronto.
En Windows, la forma estándar es CryptGenRandom () .
fuente
No estaba satisfecho con ninguna de las respuestas hasta ahora, así que escribí una nueva función flotante aleatoria. Hace suposiciones bit a bit sobre el tipo de datos flotante. Todavía necesita una función rand () con al menos 15 bits aleatorios.
fuente
En mi opinión, la respuesta anterior da un flotador 'aleatorio', pero ninguno de ellos es realmente un flotador aleatorio (es decir, pierden una parte de la representación del flotador). Antes de apresurarme en mi implementación, primero echemos un vistazo al 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 oscila entre -127 y 126. La función más simple (y en realidad más aleatoria) es simplemente escribir los datos de un int aleatorio en un flotante, así
tenga en cuenta que si lo hace
float f = (float)rand();
, convertirá el entero en un flotante (por lo tanto, 10 se convertirá en 10.0).Entonces, si desea limitar el valor máximo, puede hacer algo como (no estoy seguro si esto funciona)
pero si observa la estructura del flotador, puede ver que el valor máximo de un flotador es (aprox.) 2 ^ 127, que es mucho mayor que el valor máximo de un int (2 ^ 32), lo que descarta una parte significativa de Los números que pueden ser representados por un flotador. Esta es mi implementación final:
El uso de esta función
randf(0, 8, 0)
devolverá un número aleatorio entre 0.0 y 255.0fuente
int e = (rand() % (max_exp - min_exp)) + min_exp_mod;
y la mantisa:int f = (int)(frac_mod * (float)rand() / RAND_MAX);
reemplazando sus respectivas líneas arriba. Tenga en cuenta que el error de mantisa es importante: ¡para losRAND_MAX
más pequeños1 << 23
solo aleatorizaría los bits significativos más bajos y obtendría ceros para los bits más significativos todo el tiempo!Si sabe que su formato de coma flotante es IEEE 754 (casi todas las CPU modernas, incluidas Intel y ARM), puede construir un número aleatorio de coma flotante a partir de un entero aleatorio utilizando métodos basados en bits. Esto solo debe considerarse si no tiene acceso a C ++ 11
random
oBoost.Random
ambos son mucho mejores.Esto dará una mejor distribución que una que usa división.
fuente
return (float)random23 / (1 << 23)
. (Sí, acabo de probar esto , modificando su función para tomarlarandom32
como parámetro y ejecutándola para todos los valores desde cero hasta(1 << 23)-1
. Y sí, su método realmente da exactamente los mismos resultados que la división por1 << 23
.)Para C ++, puede generar números flotantes reales dentro del rango especificado por la
dist
variablefuente
rand () devuelve un int entre 0 y RAND_MAX. Para obtener un número aleatorio entre 0.0 y 1.0, primero arroje el retorno int por rand () a un flotante, luego divida por RAND_MAX.
fuente
No pude publicar dos respuestas, así que aquí está la segunda solución. log2 números aleatorios, sesgo masivo hacia 0.0f pero es realmente un flotador aleatorio de 1.0f a 0.0f.
fuente