Pergunta

para o meu programa eu preciso de pseudo números inteiros aleatórios com intervalos diferentes.Até agora eu usei a função aleatório (), mas ele tem suas limitações.

Eu achei o boost::aleatório biblioteca de ser muito melhor substituição, mas eu não queria criar geradores aleatórios em todo o lugar.
( Eu preciso de números inteiros aleatórios em muitas classes, porque é um software de teste de estresse que faz com que cada decisão de forma pseudo-aleatória ( -> executar um teste tem de ser repetitivo, definindo a mesma semente ) ).

É por isso que eu capsuled boost::aleatório de distância, na minha própria classe.

A idéia por trás disso é a facilidade do uso, de modo que é quase tão simples como o C++ rand() método

#include "boost/shared_ptr.hpp"
#include "boost/random.hpp"

class Random{
public:
   typedef boost::shared_ptr< Random > randomPtr;
   typedef boost::mt19937 randomGeneratorType;

   static randomPtr Get(){
      static randomPtr randomGen( new RandomGenerator() );
      return randomGen;
   }

   void SetSeed(int seed){
      randomGenerator.seed( seed );
   }

   int Random( int lowerLimit, int upperLimit ){
   boost::uniform_int<> distribution( lowerLimit, upperLimit );
   boost::variate_generator< randomGeneratorType&, boost::uniform_int<> >
   LimitedInt( randomGenerator , distribution );
   return LimitedInt();
   }

private:
   // prevent creation of more than one object of the LogManager class
   // use the Get() method to get a shared_ptr to the object
  Random():
    randomGenerator() //initialize randomGenerator with default constructor
  {}

  RandomGenerator( const RandomGenerator& orig ){};

  randomGeneratorType randomGenerator;
};

A geração de um número aleatório dentro de um determinado intervalo agora vai ser tão fácil como

#include "Random.h"
  Random::Get()->SetSeed( 123123 );  // If you want to make the run repeatable
  int dice = Random::Get()->Random(1,6);

Pergunta:
Há algo de errado com esta forma de geração de números aleatórios?
Grande sobrecarga eu não reconheço ?
Pura Maldade ou desatualizados técnica de programação ?

( Eu ainda sou novo para c++ e quer melhorar minhas habilidades, e eu descobri que o estouro de Pilha é o melhor lugar para obter alta qualidade e aconselhamento )

Foi útil?

Solução

Joe Gauterin demonstrou o problema, no entanto, não ofereceu nenhuma solução :)

O problema com o estado compartilhado é a ausência de reentrada: ou seja, executar o dobro do mesmo método não fornece o mesmo resultado. Isso é particularmente crítico em situações multithreads, porque o estado global nem sempre muda no mesmo ponto do programa, levando a resultados inconsistentes de uma execução para outra.

A solução é que cada simulação deve ter seu próprio "estado" e você evitará o estado compartilhado.

Isso pode ser realizado de várias maneiras: você ainda pode usar um estado "global", mas torná -lo local para um segmento, por exemplo, portanto, os threads não pisariam nos dedos um do outro.

A versão mais limpa, no entanto, consiste em armazenar esse estado em algum lugar, e a maneira mais fácil é ter algum tipo de Context classe, instanciada uma vez por simulação, e que é um agregado do estado da simulação (para o estado em toda a simulação).

Com aquilo em mente:

class Context
{
public:
  typedef boost::mt19937 RandomGeneratorType;

  void SetSeed(int seed){
     rg.seed( seed );
  }

  int Next( int lowerLimit, int upperLimit ) {
    boost::uniform_int<> distribution( lowerLimit, upperLimit );
    boost::variate_generator< randomGeneratorType&, boost::uniform_int<> >
    LimitedInt( rg, distribution );
    return LimitedInt();
  }

private:
  RandomGeneratorType rg;
};

Então, passe o Context Instância em sua simulação e você pode executar o máximo que desejar em paralelo.

Outras dicas

Você basicamente envolto seu gerador em um singleton, a introdução de todos os problemas que singletons e variáveis globais transportar.Por exemplo, você teria dificuldade para obtenção de vários testes de estresse executando em paralelo, como a sua implementação não é thread-safe.

Mas o principal problema que eu vejo é que o seu invólucro, não mais simples do que apenas usando o boost::aleatório, sem embalagem.

Você provavelmente poderia evitar Get(). Isso é puramente subjetivo, para mim. Eu preferiria um mecanismo de chamada como Random::Seed() e Random::Next() ou Random::Next(min,max). Não há muita função aleatória, então você pode torná -los todas as funções estáticas.

Aqui está uma implementação simples. Mas lembre-se de que isso está considerando que você está usando isso em um ambiente de thread único. Para um ambiente multithread, é melhor não tê-lo como um singleton.

class Random
{
public:
    typedef boost::mt19937 RandomGeneratorType;

    static void Seed(int seed)
    {
        s_randGen.seed(seed);
    }

    static int NextInt(int min_val, int max_val)
    {
        boost::uniform_int<> distribution(min_val, max_val);boost::variate_generator< randomGeneratorType&, boost::uniform_int<> >
        return LimitedInt( s_randGen , distribution );;
    }
private:
    static RandomGeneratorType s_randGen;
};

Random::RandomGeneratorType Random::s_randGen;

Abaixo está minha versão do encapsulamento:

#include <boost/random.hpp>
#include <ctime>  


int getRandomIntValue(int min, int max)
{
    static boost::minstd_rand gen((unsigned int)std::time(NULL));
    boost::uniform_int<int> dist(min, max);
    boost::variate_generator<
        boost::minstd_rand&,
        boost::uniform_int<int>> combgen(gen, dist);

    return combgen();
}

Eu diria que isso parece bom - dessa maneira você pode substituir facilmente seu algo de geração aleatória, caso seja necessário.

Você também pode tentar algo como criar entidade em um contêiner e embaralhar aleatório.

void
GenerateRandomString(vector<string>& container,
                     int size_of_string,
                     unsigned long long num_of_records,
                     int thread_id)
{
  srandom(time(0));
  random();
  for(unsigned long long int i=0; i < num_of_records; ++i)
  {
    stringstream str_stream;
    str_stream.clear();
    str_stream << left << setfill('x') << setw(size_of_string-4);
    str_stream << num_of_records+i+1 << "-" << thread_id;
    container.push_back(str_stream.str());
  }
  random_shuffle(container.begin(), container.end());
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top