Generating random numbers C++

Asked

Viewed 4,203 times

0

Hi, I’m writing a simulation in C++ and I have to generate some random numbers. To do this, initialize ( srand(time(NULL)) once and I have a method as follows:

void Supermercado::geraTempoProximoCliente() {
    int intervaloProximoCliente = rand()%(2*tempoMedioChegada-1) +1;

    printf("Intervalo para chegar outro cliente %d\n",intervaloProximoCliente);

    tempoChegadaProximoCliente = getRelogio() + intervaloProximoCliente;
}

Would anyone like to tell me why every time my program generates a new interval, it is always the same throughout the entire execution of the program? Builder where seed is generated:

Supermercado::Supermercado(string nome_,int tempoSimulacao_,inttempoMedioChegada_,
    int numeroDeCaixas_, int tamanhoMaximoDasFilas, Caixa caixas[]) {
listaDeCaixas = new CircularList<Caixa>();
tempoMedioChegada = tempoMedioChegada_;
relogio = 0;
clientesDesistentes = 0;
valorDesistentes = 0;
numeroDeCaixas = numeroDeCaixas_;
tempoSimulacao = tempoSimulacao_;
tempoChegadaProximoCliente = 0;
srand(time(NULL));
for(int i = 0; i < numeroDeCaixas; i++)
    listaDeCaixas -> push_back(caixas[i]);
}

I urge the supermarket once only on Main and call the method run from it.

The method perform:

void Supermercado::executa() {
    bool continua = true;
    Caixa caixa;
    geraTempoProximoCliente();
    while(relogio != tempoSimulacao*3600) {
        if(relogio == tempoChegadaProximoCliente)
            geraTempoProximoCliente();
    }
    relogio++;
}
  • Where are you generating the seed? His problem is where it is.

  • I am generating in the Supermarket class builder, in the main I instate a Supermarket and call the method run from it. Where would be the mistake in that? I’m cracking my head on this

  • Unless srand should be initialized in the method that Rand will be called, but then it would still be stuck because it would need to generate different random numbers at each call of the method.

  • Enter the code for us to see. But it seems that the problem is to have put in the constructor.

  • I edited the question with the builder of the Supermarket.

  • I can’t reproduce your problem. http://ideone.com/ao2qah

  • Yes, seeing your link I realize that my method should work properly.

  • Maybe if you try to make a [mcve] or find the mistake on your own or at least give better subsidies for us to help.

  • Why not use the Mersenne Twist library to generate the numbers? for me the best algorithm of random numbers. https://www.cs.hmc.edu/~Geoff/mtwist.html Only download to include in project folder

  • Thanks for the tip, Andrey. It was solved, I found a srand lost in the builder of another class that is instantiated all the time, this was causing the repetition of the number.

Show 5 more comments

3 answers

1


C++11 can already be considered standard, and introduced a standard library for random numbers, <random>, even if it’s not the source of your problem, I’ll introduce you.

The main problem of using rand() and truncate the bits with % is that the distribution of bits in rand is not guaranteed to be uniform. Even if funcione™ in your case, I recommend using the new libraries that ensure the standard implementation of the pseudo-random generator.

Basically, you need to declare a number generator. One of the ones provided by the standard library is a 32-bit Mersenne Twister:

#include <random>
std::mt19937 mt(42); //gerador mersene twist, inicializado com seed = 42

Then you need to define how you want to map its pseudo-random output (much better than improvising with the operator %). If you want integers between zero and one hundred, evenly distributed, for example:

//distribuição linear de inteiros entre 0 e 100
std::uniform_int_distribution<int> linear_i(0, 100);

You already want real numbers linearly distributed between 0.0 and 100.0, for example:

//distribuição linear de números reais entre 0 e 100
std::uniform_real_distribution<float> linear_r(0.f, 100.f);

Once you have initialized the generator and the distribution (you can save them as a class member), every time you need a number, just call the desired distribution to map a number generated by the generator:

int   aleatorio_i = linear_i( mt ); //inteiro pseudo-aleatório
float aleatorio_f = linear_r( mt ); //float pseudo-aleatório

You can test the example I created here.

The best of the new library is that it has several ready-made distributions. The case you present - interval between arrival of customers - for example, can be modeled by a normal distribution around the average.

A while ago I made an example code of distributions. Maybe I’ll be the guide.

-1

Use srand(time(0)) instead of srand(time(NULL)). See if it works.

-1

Always set function srand() before function Rand(). What do you call the Rand() in

void Supermercado::geraTempoProximoCliente()

Then put the srand() before the code

int intervaloProximoCliente = rand()%(2*tempoMedioChegada-1) +1;

Thus ending:

void Supermercado::geraTempoProximoCliente() {
    srand(time(NULL));
    int intervaloProximoCliente = rand()%(2*tempoMedioChegada-1) +1;
    printf("Intervalo para chegar outro cliente %d\n",intervaloProximoCliente);
    tempoChegadaProximoCliente = getRelogio() + intervaloProximoCliente;
}

In doing so, you ensure that every time you generate a new number, the program captures a new system time to use in the function Rand().

I hope I’ve helped!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.