How to generate large random numbers in C++?

Asked

Viewed 1,585 times

8

I’m looking to make a random number generator of [0.4], including these, only the problem is my teacher indicated that I used 4 million to generate random numbers and what value surpasses RAND_MAX , then it’s two questions:

  1. How to generate numbers double random?
  2. 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");
}

3 answers

10


It depends on the compiler, probably using a bad one. See that this one reaches 2 billion. Of course, every compiler that manages at least 32767 is within the standard.

If you don’t need it to give all integers you can do a multiplication until you reach the desired value.

If you are using C++11 up, and should, then you can use the modern library of the C++:

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

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

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

  • Who generates random numbers is the implementation of the default API at runtime, not the compiler.

  • But it depends on which compiler the API will use. I spoke in the sense of the set. , not that it is the compiler that does this.

5

You have several options to generate very large numbers.

First, you can draw multiple numbers and merge into one. But be careful not to create non-uniform generators and use as if they were. For example, if the rand() draw from 0 to 32767(2 15-1), you can create 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 draw 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 draw from 0 to 35184372088831 (2 45-1), also uniformly. Another option is to create your own linear congruent generator of pseudo-random numbers (the same methodology used by libraries) with a wikipedia orientation. So you can make a randomizer the way you prefer.

https://en.wikipedia.org/wiki/Linear_congruential_generator https://en.wikipedia.org/wiki/Linear_congruential_generator

The following, for example, I have just created to answer your question. I don’t know if it generates quality because I haven’t tested it, but it actually generates uniformly numbers from 0 to 4294967295 (2 32-1), probably has more performance running than the previous ones and doesn’t need it to call srand() to generate randomness (uses by default as seed the clock), but also does not accept Seed specification in case of need.

# 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 and find a suitable way, you can even create generators that generate type numbers long long unsigned int ranging from 0 to 18446744073709551615 (2 64-1), but for this it needs something better worked using more than one state variable.

As for the generation of large numbers, it has an absurdly large number of options. As for the generation of numbers of type double, I don’t know if that’s what you want to know, but the most common way to do that is rand()/(RAND_MAX+1.0), that will draw uniformly type numbers double ranging from 0,000 (including) to 1,000 (excluding).

You can make adaptations for better draw quality, higher performance and different properties (such as including the 1,000 or excluding the 0,000). In my opinion, a good way to draw double is the following, which modifies the code of the random() previously created to make uniform and continuous draw between two type numbers 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, has better performance than doing the split with implicit Typecast. It is mathematically good because it has high granularity, thus portraying well the continuity property of the draw.

Any doubt?

2

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

It is guaranteed by the standard that RAND_MAX never has a value less than 32.767, what makes it rand() always return a random number of at least, 15 bits.

The pattern C99 ensures that the unsigned long long have at least 64 bits, that is, track between 0 and 18.446.744.073.709.551.615.

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

With due logical processing, it is possible to "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;
}

Exit:

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

    Just one note that I remembered: the random number generator in your compiler’s standard library may have a distinct entropy between high and low bits. If, by chance, the entropy of the first 7 bits is low, but that of the other 8 bits is high, you may notice that the resulting number of this operation is not as random as you expect. By low entropy understand that the pattern repeats, that there is little change between a random number and its consecutive

  • 1

    @Jeffersonquesado: Well observed. The entropy of the random number series generated through this technique is very low and may not be suitable for certain applications.

Browser other questions tagged

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