How to generate large random numbers in C ++?

7

I'm trying to make a random number generator of [0,4], including these, but the problem is my teacher indicated that I used 4 million to generate random numbers and that value exceeds% with% / strong>, then there are two questions:

  • How to generate% random numbers%?
  • How to generate random with an interval greater than RAND_MAX ?
  • Code:

    #include <cstdlib>
    #include <set>
    #include <iostream>
    #include <windows.h>
    #include <time.h>
    #include <vector>
    
    using namespace std;
    
    int main(int argc, char** argv) {
        double populacao[10];
        double aptidao[10];
        srand((unsigned) time(NULL));
    
        for(int i=0; i<10; i++) {
            populacao[i]=(((rand()%400000)/4000000.0)*4);
            cout<<populacao[i]<<endl;
            aptidao[i]=populacao[i];
        }
        system("Pause");
    }
    
        
    asked by anonymous 16.08.2017 / 19:00

    3 answers

    9

    Depends on the compiler, probably using a bad one. See that reaches 2 billion . Of course, any compiler that manages at least 32767 is within the default.

    If you do not need to be able to give all integers you can multiply until you reach the desired value.

    If you're using C ++ 11 up, and should, then you can use the more modern C ++ library :

    #include <iostream>
    #include <random>
    using namespace std;
    
    int main() {
        default_random_engine generator;
        uniform_int_distribution<int> distribution(0, 4000000);
        double populacao[10];
        double aptidao[10];
        for (int i = 0; i<10; i++) {
            populacao[i] = distribution(generator);
            cout << populacao[i] << endl;
            aptidao[i] = populacao[i];
        }
    }
    

    See running on ideone . And at Coding Ground . Also I put GitHub for future reference .

    Outside this you have to create more complex formulas or even use an alternate generator, which I do not find interesting in most cases.

        
    16.08.2017 / 19:28
    5

    You have several options for generating very large numbers.

    First, you can raffle multiple numbers and merge into one. But be careful not to create non-uniform generators and use them as if they are. For example, if rand() draws from 0 to 32767 (2 ^ 15-1), you can create the uniform generator

    int rand2(){
        int temp = rand() ; // Sorteia uniformemente número de 0x0000 a 0x7FFF
        temp <<= 15 ;       // Agora é de 0x00000000 a 0x3FFF8000, múltiplo de  0x8000
        temp += rand() ;    // Agora é sorteio uniforme de 0x00000000 a 0x3FFFFFFF
        return temp ;
    }
    

    to sort from 0 to 1073741823 (2 ^ 30-1) or you can also use

    long long int rand3(){
        long long int temp = rand2() ; // Sorteia uniformemente número de 0x0000 a 0x3FFFFFFF
        temp <<= 15 ;                  // Agora é de 0x00000000 a 0x1FFFFFFF8000, múltiplo de  0x8000
        temp += rand() ;               // Agora é sorteio uniforme de 0x00000000 a 1FFFFFFFFFFF
        return temp ;
    }
    

    to sort from 0 to 35184372088831 (2 ^ 45-1), also uniformly. Another option is to create your own congruent linear generator of pseudo-random numbers (same methodology used by libraries) with a wikipedia orientation. So you can make a randomizer the way you like.

    link link

    The following, for example, I just created to answer your question. I do not know if it generates quality because I have not tested it, but it actually generates numbers from 0 to 4294967295 (2 ^ 32-1), probably performs better than previous ones, and does not have to call srand() to generate randomness uses by default as the seed the clock), but also does not accept seed specification in case it needs.

    # include <time.h>
    unsigned int random(){
        static long long unsigned int state = time(0) ;     // Estado inicial (semente)
        state = 0x23A7489B29LL + 0x50FB738205C1LL * state ; // Atualizar estado atual
        return (unsigned int)( state>>32 ) ;                // Gerar a partir do estado
    }
    

    If you want to find a suitable way, you can even create generators that generate long long unsigned int numbers ranging from 0 to 18446744073709551615 (2 ^ 64-1), but for this you need something better worked out using more than one state variable.

    As for the generation of large numbers, it has an absurdly large number of options. As far as generating numbers of type double , I do not know if that's what you want to know, but the most common way of doing this is rand()/(RAND_MAX+1.0) , which will uniformly sort numbers double ranging from 0.000 (including -o) to 1,000 (excluding it).

    You can make adaptations for better raffle quality, higher performance, and different properties (such as 1,000 or 0,000 excluded). In my opinion, a good way to sort double is as follows, which modifies the code of random() created earlier to make a uniform and continuous draw between two numbers of type double .

    # include <time.h>
    double random( double number1 , double number2 ){
        static long long unsigned int state = time(0) ;                             // Estado inicial (semente)
        state = 0x23A7489B29LL + 0x50FB738205C1LL * state ;                         // Atualizar estado atual
        double zeroToOne ;
        *(long long unsigned int*)&zeroToOne = ( state>>12 )+0x3FF0000000000000LL ; // Gerando número de 0.0 a 1.999999999999999778
        zeroToOne -= 0.999999999999999889 ;                                         // Agora é de 0.000000000000000111  a 0.999999999999999889
        return number1*( 1.0-zeroToOne )+( zeroToOne )*number2 ;                    // Retorna um número aleatório que vai de number1 a number2
    }
    

    According to tests I did years ago, it performs better than doing division with typecast implicitly. It is mathematically good because it has high granularity, thus well portraying the continuity property of the draw.

    Any questions?

        
    18.08.2017 / 03:26
    2

    The function rand() is able to return integers in the range between 0 and RAND_MAX .

    It is guaranteed by default that RAND_MAX never has a value less than 32.767 , which causes rand() to always return a random number of at least 15 bits .

    The default C99 ensures that unsigned long long has at least 64 bits , that is, the range between 0 and 18.446.744.073.709.551.615 .

    Starting from these premises, if each call of the function rand() is able to return me 15 bits random, with 5 calls I am able to accumulate 75 bits .

    With proper logical processing, you can "mount" a random number of 64 bits , with a portable implementation C99 , let's see:

    unsigned long long llrand( void )
    {
        unsigned long long ret = 0;
    
        for( int i = 0; i < 5; i++ )
        {
            ret = (ret << 15) | (rand() & 0x7FFF);
        }
    
        return( ret & 0xFFFFFFFFFFFFFFFFULL );
    }
    

    Test code:

    #include <cstdlib>
    #include <iostream>
    #include <ctime>
    
    
    unsigned long long llrand( void )
    {
        unsigned long long ret = 0;
    
        for( int i = 0; i < 5; i++ )
        {
            ret = (ret << 15) | (std::rand() & 0x7FFF);
        }
    
        return( ret & 0xFFFFFFFFFFFFFFFFULL );
    }
    
    
    int main( void )
    {
        std::srand(std::time(NULL));
    
        for( int i = 0; i < 20; i++ )
        {
            std::cout << llrand() << std::endl;
        }
    
        return 0;
    }
    

    Output:

    $ ./rand64 
    8105869587383598689
    6277277725189066831
    1509360212795395722
    1130692503851307412
    14335258242796316152
    5075740159224506903
    14680498390136040740
    7165466167364905026
    16797692089103744121
    16486198844466236119
    7276392683204141714
    8357279606092084573
    16367915918020953270
    16380497907074646611
    16976708914435940256
    10292415635872591979
    13954955472883015315
    6877101750998155002
    11106815715087335245
    5831095514054045134
    
        
    16.08.2017 / 20:41