Geração aleatória de números flutuantes


271

Como gerar flutuações aleatórias em C ++?

Eu pensei que poderia pegar o rand inteiro e dividi-lo por algo, isso seria suficiente?


2
Depende do que você deseja o número e do quão aleatório. normalmente rand () fornecerá 15 bits de aleatoriedade, mas os flutuadores terão precisão de 23 bits, portanto, perderão alguns valores.
Pete Kirkham

1
Atualizei minha resposta para incluir todas as principais opções disponíveis e minha opção de focar no randomcabeçalho adicionado no C ++ 11 é reforçada pelo documento padrão N3924: Desencorajando rand () no C ++ 14 . Incluo rand()na minha resposta a maioria das considerações históricas, mas também a realização de aplicativos herdados.
Shafik Yaghmour

Minha resposta inclui como evitar os mesmos números de cada vez com o <random>cabeçalho
Andreas DM

Respostas:


381

rand()pode ser usado para gerar números pseudo-aleatórios em C ++. Em combinação com RAND_MAXe um pouco de matemática, você pode gerar números aleatórios em qualquer intervalo arbitrário que escolher. Isso é suficiente para fins de aprendizado e programas de brinquedos. Se você precisar de números verdadeiramente aleatórios com distribuição normal, precisará empregar um método mais avançado.


Isso irá gerar um número de 0,0 a 1,0, inclusive.

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

Isso irá gerar um número de 0,0 a alguns arbitrário float, X:

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

Isso irá gerar um número de arbitrário LOpara arbitrário HI:

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

Observe que a rand()função geralmente não será suficiente se você precisar de números verdadeiramente aleatórios.


Antes de ligar rand(), você deve "propagar" o gerador de números aleatórios ligando srand(). Isso deve ser feito uma vez durante a execução do seu programa - não uma vez toda vez que você ligar rand(). Isso geralmente é feito assim:

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

Para ligar randou srandvocê deve #include <cstdlib>.

Para ligar time, você deve #include <ctime>.


22
Não se esqueça de semear primeiro!
26710 Klaim

14
É melhor observar que os dois limites são inclusivos.
dmckee --- ex-moderador gatinho

14
Esta resposta é enganosa. Foi coberto no Going Native 2013 na semana passada; rand () Considerado nocivo, channel9.msdn.com/Events/GoingNative/2013/… para uma explicação muito detalhada.
Ade Miller

14
Não entendo por que tantas pessoas aprovaram esta resposta. É matematicamente incorreto. RAND_MAX é um número muito pequeno (geralmente 2 ^ 16). Isso significa que, a partir de 23 bits do ponto flutuante, você faz apenas 15 aleatoriamente. Os outros provavelmente serão zero. Você realmente obterá números aleatórios em distribuição uniforme, mas de baixa precisão. Por exemplo, seu gerador aleatório pode gerar 0,00001 e 0,00002, mas não pode gerar 0,000017. Portanto, você tem uma distribuição uniforme, mas de baixa precisão (256 vezes menos precisão que o ponto flutuante real).
precisa saber é o seguinte

10
@DanielHsH: O OP perguntou especificamente com o que a mecânica poderia ser usada para gerar carros alegóricos aleatórios rand(). Esta pergunta e minha resposta foram focadas especificamente no aprendizado do básico e não estavam preocupadas com altos graus de precisão. Você precisa aprender a andar antes de aprender a correr.
precisa saber é o seguinte

137

O C ++ 11 oferece muitas novas opções com random. O artigo canônico sobre esse tópico seria N3551, Geração de Número Aleatório em C ++ 11

Para entender por que o uso rand()pode ser problemático, consulte o material de apresentação rand () Considerável Nocivo de Stephan T. Lavavej, fornecido durante o evento GoingNative 2013 . Os slides estão nos comentários, mas aqui está um link direto .

Também abordo booste uso, randpois o código legado ainda pode exigir seu suporte.

O exemplo abaixo é destilado do site cppreference e usa o mecanismo std :: mersenne_twister_engine e o std :: uniform_real_distribution que gera números no [0,10)intervalo, com outros mecanismos e distribuições comentados ( veja ao 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';
    }
}

a saída será semelhante à seguinte:

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

A saída variará dependendo da distribuição que você escolher, portanto, se decidirmos usar std :: normal_distribution com um valor 2para mean e stddev, por exemplo, dist(2, 2)a saída será semelhante a esta ( veja ao vivo ):

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

A seguir está uma versão modificada de alguns dos códigos apresentados em N3551( veja ao vivo ):

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

std::default_random_engine & global_urng( )
{
    static std::default_random_engine u{};
    return u ;
}

void randomize( )
{
    static std::random_device rd{};
    global_urng().seed( rd() );
}

int main( )
{
  // Manufacture a deck of cards:
  using card = int;
  std::array<card,52> deck{};
  std::iota(deck.begin(), deck.end(), 0);

  randomize( ) ;  

  std::shuffle(deck.begin(), deck.end(), global_urng());
  // Display each card in the shuffled deck:
  auto suit = []( card c ) { return "SHDC"[c / 13]; };
  auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };

  for( card c : deck )
      std::cout << ' ' << rank(c) << suit(c);

   std::cout << std::endl;
}

Os resultados serão semelhantes a:

5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S

Impulso

É claro que o Boost.Random também é sempre uma opção, aqui estou usando boost :: random :: 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 ()

Se você precisar usar rand(), podemos consultar as Perguntas frequentes sobre C, para obter um guia sobre Como gerar números aleatórios de ponto flutuante? , que basicamente fornece um exemplo semelhante a este para gerar um no intervalo [0,1):

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

e gerar um número aleatório no intervalo de [M,N):

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}

1
você pode consertar seus randMToNpls? observe que é [M,N]ou adicione novamente o + 1.item acima randZeroToOne. -> pensar em chamá-lo assim:randMToN(0.0, 1.0);
BeyelerStudios

1
Também tenha cuidado com a divisão por zero em (N-M). Uma boa maneira de lidar com esse erro é encontrada aqui: stackoverflow.com/questions/33058848/…
Dr. Beco

61

Dê uma olhada no Boost.Random . Você poderia fazer algo assim:

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

Brincando, é melhor passar o mesmo objeto mt19937 ao invés de construir um novo a cada vez, mas espero que você entenda.


1
uniform_real usa um intervalo semiaberto [min, max), o que significa que você obterá seu valor mínimo, mas nunca atingirá o valor máximo. É algo a considerar, embora, se você arredondar de alguma forma, possa superar esse problema.
TehWan

20
Agora isso faz parte do C ++ 11.
Tomas Andrle

@Wolf em aplicações práticas, as chances de atingir qualquer valor específico de ponto flutuante são tão baixas que não importa se o ponto final está incluído ou excluído. Se você precisa max, mas pode usar um open-ended min, você pode reverter o intervalo facilmente: return min + max - gen();.
Mark Ransom

26

No moderno, c++você pode usar o <random>cabeçalho que acompanha o produto c++11.
Para obter aleatórios float, você pode usar std::uniform_real_distribution<>.

Você pode usar uma função para gerar os números e, se não quiser que os números sejam sempre iguais , defina o mecanismo e a distribuição static.
Exemplo:

float get_random()
{
    static std::default_random_engine e;
    static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
    return dis(e);
}

É ideal colocar os floatem um recipiente como std::vector:

int main()
{
    std::vector<float> nums;
    for (int i{}; i != 5; ++i) // Generate 5 random floats
        nums.emplace_back(get_random());

    for (const auto& i : nums) std::cout << i << " ";
}

Exemplo de saída:

0.0518757 0.969106 0.0985112 0.0895674 0.895542

std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1é tecnicamente incorreto, 1.0 nunca será gerado, consulte pt.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.
Troyseph

1
Esta deve ser a resposta aceita, está enlouquecendo 2020.
Alex

25

Chame o código com dois floatvalores, o código funciona em qualquer intervalo.

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

Vale ressaltar que este é um caso de uso potencial para fmaf()(ou a fma()sobrecarga de flutuação em C ++) em C99 ou C ++ 11, que pode preservar mais precisão. Como em fmaf((float)rand() / RAND_MAX, b - a, a).
Tim Čas 9/08/19

22

Se você estiver usando C ++ e não C, lembre-se de que no relatório técnico 1 (TR1) e no rascunho de C ++ 0x eles adicionaram recursos para um gerador de números aleatórios no arquivo de cabeçalho, acredito que seja idêntico ao Boost. Biblioteca aleatória e definitivamente mais flexível e "moderna" que a função de biblioteca C, rand.

Essa sintaxe oferece a capacidade de escolher um gerador (como o twister de Mersenne mersenne mt19937) e depois escolher uma distribuição (normal, bernoulli, binomial etc.).

A sintaxe é a seguinte (vergonhosamente emprestado deste site ):

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

2
Agora, no C ++ 11, também dist pode ser inicializado com os valores mínimo e máximo.
Étienne

Parece estranho para mim colocar o mínimo e o máximo no inicializador e fornecer o gerador ao obter um valor - eu preferiria que fosse o contrário, tudo bem.
yoyo

6

Em alguns sistemas (o Windows com o VC vem à mente, atualmente), RAND_MAXé ridiculamente pequeno, i. e apenas 15 bits. Ao dividir porRAND_MAX você você está gerando apenas uma mantissa de 15 bits em vez dos 23 bits possíveis. Isso pode ou não ser um problema para você, mas você está perdendo alguns valores nesse caso.

Ah, acabei de notar que já havia um comentário para esse problema. De qualquer forma, aqui estão alguns códigos que podem resolver isso para você:

float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);

Não testado, mas pode funcionar :-)


E quanto a float r = (float) ((rand () << 9) | rand ()) / RAND_MAX? (também não testado)
Trap

Argh, desculpe, dividir por RAND_MAX não o levará a lugar algum ... o objetivo desse truque era ter algo maior que RAND_MAX ... corrigido isso para mim também.
Joey

2
Tenha cuidado ao compor números aleatórios sem teoria ... chamadas consecutivas para rand () podem não ser completamente independentes. Dica: se o seu linear congruente gerador, assistir a baixa pouco sobre chamadas consecutivas: alterna entre 0 e 1.
RBerteig

Eu sei. Para algumas aplicações, isso pode ser suficiente. Mas sim, você provavelmente deve usar mais do que apenas duas chamadas neste caso. Não existe uma bala de prata nesse caso, você não pode nem confiar que é um LCG. Outros PRNGs têm bits altos fracos. A solução Boost deve ser a melhor aqui.
314 Joey

(Nota: o bit baixo retornado por rand no MSVC não é o bit mais baixo do estado RNG. Para chamadas de 100 rand (), recebo o seguinte: 1100100000111111101010010010011010101110110110111010010011111110010000000001010001101100001001001111001000000000101000110110000100100101100011. Java parece um LCG de 48 bits e apenas usa 32 bits, para fazê-lo da mesma forma)
Joey

4

drand48(3)é a maneira padrão POSIX. O GLibC também fornece uma versão reentrante drand48_r(3).

A função foi declarada obsoleta no SVID 3, mas nenhuma alternativa adequada foi fornecida, portanto, o IEEE Std 1003.1-2013 ainda a inclui e não possui anotações de que está indo para algum lugar em breve.

No Windows, a maneira padrão é CryptGenRandom () .


2

Eu não estava satisfeito com nenhuma das respostas até agora, então escrevi uma nova função de flutuação aleatória. Faz suposições bit a bit sobre o tipo de dados flutuante. Ele ainda precisa de uma função rand () com pelo menos 15 bits aleatórios.

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}

7
abordagem interessante, eu gostaria de upvote, mas eu realmente não entendo o que está acontecendo
Hasen

2

Na minha opinião, a resposta acima fornece algum valor flutuante 'aleatório', mas nenhum deles é realmente um valor flutuante aleatório (ou seja, eles perdem uma parte da representação do valor flutuante). Antes de entrar na minha implementação, vamos primeiro dar uma olhada no formato padrão ANSI / IEEE para carros alegóricos:

| sinal (1 bit) | e (8 bits) | f (23 bits) |

o número representado por esta palavra é (-1 * sinal) * 2 ^ e * 1.f

observe que o número 'e' é um número tendencioso (com um viés 127), variando de -127 a 126. A função mais simples (e realmente mais aleatória) é simplesmente gravar os dados de um int aleatório em um float, portanto

int tmp = rand();
float f = (float)*((float*)&tmp);

note que se você fizer float f = (float)rand();isso converterá o número inteiro em um ponto flutuante (assim, 10 se tornará 10.0).

Então agora, se você deseja limitar o valor máximo, pode fazer algo como (não tenho certeza se isso funciona)

int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f       // note float to int conversion!
tmp %= max_number;
f -= tmp;

mas se você olhar para a estrutura do flutuador, poderá ver que o valor máximo de um flutuador é (aproximadamente) 2 ^ 127, que é muito maior que o valor máximo de um int (2 ^ 32), excluindo assim uma parte significativa de os números que podem ser representados por um flutuador. Esta é minha implementação final:

/**
 * Function generates a random float using the upper_bound float to determine 
 * the upper bound for the exponent and for the fractional part.
 * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
 * @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
 * @param sign_flag if sign_flag = 0 the random number is always positive, if 
 *              sign_flag = 1 then the sign bit is random as well
 * @return a random float
 */
float randf(int min_exp, int max_exp, char sign_flag) {
    assert(min_exp <= max_exp);

    int min_exp_mod = min_exp + 126;

    int sign_mod = sign_flag + 1;
    int frac_mod = (1 << 23);

    int s = rand() % sign_mod;  // note x % 1 = 0
    int e = (rand() % max_exp) + min_exp_mod;
    int f = rand() % frac_mod;

    int tmp = (s << 31) | (e << 23) | f;

    float r = (float)*((float*)(&tmp));

    /** uncomment if you want to see the structure of the float. */
//    printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);

    return r;
}

usar esta função randf(0, 8, 0)retornará um número aleatório entre 0,0 e 255,0


1
você tem um erro. rand ()% frac_mod não funcionará, pois MAX_RAND é geralmente menor que (1 << 23).
21713 DanielHsH

Devo admitir que não sei o tamanho exato de MAX_RAND. Mesmo assim, ainda funcionará, talvez seja uma declaração inútil, mas ainda funcionará. 8% 10 = 8, tudo bem, mas se MAX_RAND for sempre menor, então (1 << 23) você poderá removê-lo.
user2546926

2
Não, você está um pouco errado. RandMax é tipicamente ~ 65.000. Isso significa que, a partir de 23 bits, você faz apenas 15 aleatoriamente. Os outros provavelmente serão zero. Você realmente obterá números aleatórios, mas de baixa precisão. Por exemplo, seu gerador aleatório pode gerar 0,001 e 0,002, mas não pode gerar 0,0017. Portanto, você tem uma distribuição uniforme, mas de baixa precisão (256 vezes menos precisão que o flutuador).
DanielHsH

Existem dois erros nesta resposta. Fixando o intervalo do expoente: int e = (rand() % (max_exp - min_exp)) + min_exp_mod;e a mantissa: int f = (int)(frac_mod * (float)rand() / RAND_MAX);substituindo suas respectivas linhas acima. Observe que o erro da mantissa é grande: para RAND_MAXmenores, 1 << 23você aleatoriamente selecionaria os bits mais baixos significativos e obteria 0s para os bits mais significativos o tempo todo!
BeyelerStudios

2

Se você sabe que seu formato de ponto flutuante é o IEEE 754 (quase todas as CPUs modernas, incluindo Intel e ARM), é possível construir um número de ponto flutuante aleatório a partir de um número inteiro aleatório usando métodos bit a bit. Isso só deve ser considerado se você não tiver acesso ao C ++ 11 randomou se Boost.Randomfor muito melhor.

float rand_float()
{
    // returns a random value in the range [0.0-1.0)

    // start with a bit pattern equating to 1.0
    uint32_t pattern = 0x3f800000;

    // get 23 bits of random integer
    uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());

    // replace the mantissa, resulting in a number [1.0-2.0)
    pattern |= random23;

    // convert from int to float without undefined behavior
    assert(sizeof(float) == sizeof(uint32_t));
    char buffer[sizeof(float)];
    memcpy(buffer, &pattern, sizeof(float));
    float f;
    memcpy(&f, buffer, sizeof(float));

    return f - 1.0;
}

Isso fornecerá uma distribuição melhor do que aquela usando divisão.


8
Não sei por que você está dizendo que isso daria uma "melhor distribuição". De fato, isso dará exatamente a mesma distribuição que apenas return (float)random23 / (1 << 23). (Sim, eu apenas testei isso , modificando sua função para tomar random32como parâmetro e executando-a para todos os valores de zero a (1 << 23)-1. E sim, seu método realmente fornece exatamente os mesmos resultados que a divisão por 1 << 23.)
Ilmari Karonen

1

Para C ++, ele pode gerar números reais de flutuação dentro do intervalo especificado pela distvariável

#include <random>  //If it doesnt work then use   #include <tr1/random>
#include <iostream>

using namespace std;

typedef std::tr1::ranlux64_base_01 Myeng; 
typedef std::tr1::normal_distribution<double> Mydist;

int main() { 
       Myeng eng; 
       eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
       Mydist dist(1,10); 

       dist.reset(); // discard any cached values 
       for (int i = 0; i < 10; i++)
       {
           std::cout << "a random value == " << (int)dist(eng) << std::endl; 
       }

       return (0);
}

1
Você acabou de copiar e colar o código desta resposta? stackoverflow.com/a/1118739/1538531
Derek

Na verdade, não. Estou um pouco surpreso ao ver o quanto eles se parecem! Mas eu inicializei o gerador de mecanismo em janeiro de 1.1970.
Marco167

Justo. Eu notei que você inicializou o gerador para a época, mas que droga, esse código é semelhante!
Derek

Acho um pouco estranho dar um exemplo do TR1, você pode explicar em que casos alguém teria que usar o TR1 em vez do C ++ 11?
Shafik Yaghmour

0

rand () retorna um int entre 0 e RAND_MAX. Para obter um número aleatório entre 0,0 e 1,0, primeiro converta o retorno int por rand () para um ponto flutuante e depois divida por RAND_MAX.


0
#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

Não consegui postar duas respostas, então aqui está a segunda solução. números aleatórios log2, viés massivo em direção a 0,0f, mas é realmente uma flutuação aleatória de 1,0f a 0,0f.

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.