Getting Big Random Numbers in C/C++

Getting big random numbers in C/C++

Here's a portable C99 solution that returns a random 64-bit number:

unsigned long long llrand() {
unsigned long long r = 0;

for (int i = 0; i < 5; ++i) {
r = (r << 15) | (rand() & 0x7FFF);
}

return r & 0xFFFFFFFFFFFFFFFFULL;
}

Explanation: rand() returns integers in the range 0 to RAND_MAX and RAND_MAX is only guaranteed to be at least 32,767 (15 random bits). long long is guaranteed to have 64 bits but may be larger.

How to generate very Large random number in c++

With c++11, using the standard random library of c++11, you can do this:

#include <iostream>
#include <random>

int main()
{
/* Seed */
std::random_device rd;

/* Random number generator */
std::default_random_engine generator(rd());

/* Distribution on which to apply the generator */
std::uniform_int_distribution<long long unsigned> distribution(0,0xFFFFFFFFFFFFFFFF);

for (int i = 0; i < 10; i++) {
std::cout << distribution(generator) << std::endl;
}

return 0;
}

Live Demo

How to generate large random numbers C

random() returns a long which on a 64bit system should be 64 bits. If you are on a 32bit system you could do the following:

#include <inttypes.h>

uint64_t num;

/* add code to seed random number generator */

num = rand();
num = (num << 32) | rand();

// enforce limits of value between 100000000 and 999999999
num = (num % (999999999 - 100000000)) + 100000000;

Alternatively on a NIX system you could read /dev/random into your buffer:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>

int fd;
uint64_t num;
if ((fd = open("/dev/random", O_RDONLY) == -1)
{
/* handle error */
};
read(fd, &num, 8);
close(fd);

// enforce limits of value between 100000000 and 999999999
num = (num % (999999999 - 100000000)) + 100000000;

A

How to generate a random int in C?

Note: Don't use rand() for security. If you need a cryptographically secure number, see this answer instead.

#include <time.h>
#include <stdlib.h>

srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.

On Linux, you might prefer to use random and srandom.

Generate big numbers with srand() in c

First of all, check RAND_MAX for the maximum value that can be generated by rand().

You could compose two rand() results into one value.

int random = (rand() << 16) | rand();

C++ Random number from 1 to a very large number (e.g. 25 million)

You could (should) use the new C++11 std::uniform_real_distribution

#include <random>

std::random_device rd;
std::mt19937 gen(rd());

std::uniform_real_distribution<> distribution(1, 25000000);

//generating a random integer:
double random = distribution(gen);

C++ Get random number from 0 to max long long integer

What is rand()?

According to this the rand() function returns a value in the range [0,RAND_MAX].

What is RAND_MAX?

According to this, RAND_MAX is "an integral constant expression whose value is the maximum value returned by the rand function. This value is library-dependent, but is guaranteed to be at least 32767 on any standard library implementation."

Precision Is An Issue

You take rand()/(double)RAND_MAX, but you have perhaps only 32767 discrete values to work with. Thus, although you have big numbers, you don't really have more numbers. That could be an issue.

Seeding May Be An Issue

Also, you don't talk about how you are calling the function. Do you run the program once with LLONG_MAX and another time with ULLONG_MAX? In that case, the behaviour you are seeing is because you are implicitly using the same random seed each time. Put another way, each time you run the program it will generate the exact same sequence of random numbers.

How can I seed?

You can use the srand() function like so:

#include <stdlib.h>     /* srand, rand */
#include <time.h> /* time */

int main (){
srand (time(NULL));
//The rest of your program goes here
}

Now you will get a new sequence of random numbers each time you run your program.

Overflow Is An Issue

Consider this part ((end - begin)*rand()/(double)RAND_MAX).

What is (end-begin)? It is LLONG_MAX or ULLONG_MAX these are, by definition, the largest possible values those data types can hold. Therefore, it would be bad to multiply them by anything. Yet you do! You multiply them by rand(), which is non-zero. This will cause an overflow. But we can fix that...

Order of Operations Is An Issue

You then divide them by RAND_MAX. I think you've got your order of operations wrong here. You really meant to say:

((end - begin) * (rand()/(double)RAND_MAX) )

Note the new parantheses! (rand()/(double)RAND_MAX)

Now you are multiplying an integer by a fraction, so you are guaranteed not to overflow. But that introduces a new problem...

Promotion Is An Issue

But there's an even deeper problem. You divide an int by a double. When you do that the int is promoted to a double. A double is a floating-point number which basically means that it sacrifices precision in order to have a big range. That's probably what's biting you. As you get to bigger and bigger numbers both your ullong and your llong end up getting cast to the same value. This could be especially true if you overflowed your data type first (see above).

Uh oh

So, basically, everything about the PRNG you have presented is wrong.

Perhaps this is why John von Neumann said

Anyone who attempts to generate random numbers by deterministic means
is, of course, living in a state of sin.

And, sometimes, we pay for those sins.

How can I absolve myself?

C++11 provides some nice functionality. You can use it as follows

#include <iostream>
#include <random>
#include <limits>
int main(){
std::random_device rd; //Get a random seed from the OS entropy device, or whatever
std::mt19937_64 eng(rd()); //Use the 64-bit Mersenne Twister 19937 generator
//and seed it with entropy.

//Define the distribution, by default it goes from 0 to MAX(unsigned long long)
//or what have you.
std::uniform_int_distribution<unsigned long long> distr;

//Generate random numbers
for(int n=0; n<40; n++)
std::cout << distr(eng) << ' ';
std::cout << std::endl;
}

(Note that appropriately seeding the generator is difficult. This question addresses that.)



Related Topics



Leave a reply



Submit