How to generate large random numbers in C++?

I want to make a random number generator of [0,4], including those, only the problem is my teacher indicated that I use 4 million to generate random numbers and what value exceeds RAND_MAX , so it's two questions:

  1. How to generate random numbers double?
  2. How to generate random with a range 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");
}
 8
Author: Maniero, 2017-08-16

3 answers

Depends on the compiler, it's probably using a bad one. See that that reaches the 2 billion . Of course every compiler that generates at least 32767 is within the standard.

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

If you're using C++11 above, and you 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 working on ideone. And no repl.it. also I put on GitHub for future reference .

Outside this has to create more complex formulas or even use an alternative generator, which I don't find interesting in most cases.

 11
Author: Maniero, 2020-06-08 17:48:25

You have several options to generate very large numbers.

First, you can draw several numbers and unite into one. But be careful not to create non-uniform generators and use as if they were. 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 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 evenly. Another option is to create your own linear congruent generator of pseudo-random numbers (same methodology used by libraries) with a Wikipedia orientation. Thus, you can make a randomizer the way you prefer.

Https://pt.wikipedia.org/wiki/Geradores_congruentes_lineares https://en.wikipedia.org/wiki/Linear_congruential_generator

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

# 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 numbers of type long long unsigned int 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 generating large numbers, it has an absurdly large number of options. As for generating numbers of type double, I don't know if that's what you want to know, but the most common way to do this is rand()/(RAND_MAX+1.0), which will evenly draw numbers of type double ranging from 0,000 (including it) to 1,000 (excluding it).

You can make adaptations for better draw quality, higher performance, and different properties (such as include 1.000 or exclude 0.000). In my opinion, a good way to draw double is the following, which modifies the code of the random() created earlier to make uniform and continuous drawing 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 implicit typecast. It is mathematically good because it has high granularity, thus portraying the continuity property of the draw well.

Any doubt?

 5
Author: RHER WOLF, 2018-02-28 20:33:34

The function rand() is capable of returning integers in the range between 0 and RAND_MAX.

Is guaranteed by the 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 the type unsigned long long has at least 64 bits, i.e. range between 0 and 18.446.744.073.709.551.615.

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

With proper logical processing, it is possible to "assemble" 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
 2
Author: Lacobus, 2017-08-17 12:35:50