Pregunta

He visto un buen número de recomendaciones para la siembra no generadores de números pseudo-aleatorios más de una vez por cada ejecución, pero nunca acompañada de una explicación detallada. Por supuesto, es fácil ver por qué el siguiente ejemplo (C / C ++) no es una buena idea:

int get_rand() {
  srand(time(NULL));
  return rand();
}

ya llamar get_rand varias veces por segundo produce resultados repetidos.

Pero no sería el siguiente ejemplo todavía ser una solución aceptable?

MyRand.h

#ifndef MY_RAND_H
#define MY_RAND_H

class MyRand
{
  public:
    MyRand();
    int get_rand() const;
  private:
    static unsigned int seed_base;
};

#endif

MyRand.cpp

#include <ctime>
#include <cstdlib>
#include "MyRand.h"

unsigned int MyRand::seed_base = static_cast<unsigned int>(time(NULL));

MyRand::MyRand()
{
  srand(seed_base++);
}

int MyRand::get_rand() const
{
  return rand();
}

main.cpp

#include <iostream>
#include "MyRand.h"

int main(int argc, char *argv[]) 
{
  for (int i = 0; i < 100; i++) 
  {
    MyRand r;
    std::cout << r.get_rand() << " ";
  }
}

es decir. a pesar de que MyRand: s constructor se llama varias veces en rápida sucesión, cada llamada a srand tiene un parámetro diferente. Obviamente, esto no es seguro para subprocesos, pero por otra parte tampoco es rand.

¿Fue útil?

Solución

Cada vez que se llama a una función de generador de números pseudo-aleatorios, el generador lleva algún estado interno y produce un número pseudo-aleatorio y un nuevo estado interno. El algoritmo para transformar el estado interno se elige cuidadosamente de modo que la salida aparece aleatoria.

Cuando la semilla del generador de números aleatorios, que está básicamente establecer este estado interno. Si restablece el estado interno a un valor predecible, si no se pierden la apariencia de aleatoriedad.

Por ejemplo, un popular, RNG simple es un generador de congruencia lineal. Los números son generados de esta manera:

X[n+1] = (a X[n] + c) mod m

En este caso, X [n + 1] es a la vez el resultado y el nuevo estado interno. Si la semilla del generador cada vez que como usted sugiere más arriba, obtendrá una secuencia que tiene este aspecto:

{(ab + c) mod m, (a(b+1) + c) mod m, (a(b+2) + c) mod m, ...}

donde b es su seed_base. Esto no se ve en absoluto al azar.

Otros consejos

Si su semilla es predecible, lo que es aquí, ya que sólo estás incrementarlo, la salida de rand () también será predecible.

Realmente depende de qué desea para generar números aleatorios, y cómo "al azar" es un azar aceptable para usted. En el ejemplo, se puede evitar duplicados en rápida sucesión, y que puede ser lo suficientemente bueno para ti. Después de todo, lo que importa es que funciona.

En casi todas las plataformas que hay una mejor manera de generar números aleatorios que rand ().

Bueno, es un procesamiento adicional que no necesita ser hecho.

En ese escenario que acababa de llamar al constructor una vez con una semilla basada en el tiempo antes del inicio del bucle. Que le garantiza resultados al azar sin el añadido extra de cambio de semillas para cada iteración.

Yo no creo que su método es cualquier más al azar que eso.

Se puede pensar en la generación de números aleatorios (esto no es estrictamente cierto en cuanto a la ejecución más, pero sirve como una ilustración) como una tabla de valores. Si recuerda hacer cualquiera de estas cosas en las estadísticas para hacer muestras aleatorias simples, una semilla, básicamente, le dice lo fila y columna para comenzar a en su gran tabla de números aleatorios. Resiembra una y otra vez es simplemente innecesario puesto que ya podemos asumir que los números se distribuyen normalmente ya.

Simplemente no hay beneficio adicional a la siembra de más de una vez ya que esto debe ser lo suficientemente bueno (dependiendo de la aplicación). Si necesita "más" números aleatorios, hay muchos métodos de generación de números aleatorios. Un caso que puedo pensar es generar números aleatorios en una forma segura para los subprocesos.

Mientras que su solución es aceptable, sus números serán sin más al azar que la siembra de una vez, a nivel mundial. srand general no debería pertenecer en un constructor. Si desea apoyar a números aleatorios, la semilla de una vez cuando el programa se inicia, y olvidarse de él.

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