I need generate random 64-bit unsigned integers using C. I mean, the range should be 0
to 18446744073709551615
. RAND_MAX
is 1073741823
.
I found some solutions in the links which might be possible duplicates but the answers mostly concatenates some rand()
results or making some incremental arithmetic operations. So results are always 18 digits or 20 digits. I also want outcomes like 5
, 11
, 33387
, not just 3771778641802345472
.
By the way, I really don't have so much experience with the C but any approach, code samples and idea could be beneficial.
You are allowed to generate a pseudo-random number of 64-bit integer as an uint64 type from the default source with the help of the Uint64() function provided by the math/rand package. So, you need to add a math/rand package in your program with the help of the import keyword to access the Uint64() function.
uint64. A 64-bit unsigned integer. It has a minimum value of 0 and a maximum value of (2^64)-1 (inclusive).
rand() function is an inbuilt function in C++ STL, which is defined in header file <cstdlib>. rand() is used to generate a series of random numbers. The random number is generated by using an algorithm that gives a series of non-related numbers whenever this function is called.
As C does not have an inbuilt function for generating a number in the range, but it does have rand function which generate a random number from 0 to RAND_MAX. With the help of rand () a number in range can be generated as num = (rand() % (upper – lower + 1)) + lower. // C program for generating a.
If you generate random numbers long enough, code will create ones like 5, 11 and 33387. If code generates 1,000,000,000 numbers/second, it may take a year as very small numbers < 100,000 are so rare amongst all 64-bit numbers. rand()simple returns random bits. A simplistic method pulls 1 bit at a time
0 If you have 32 or 16-bit random value - generate 2 or 4 randoms and combine them to one 64-bit with <<and |. uint64_t rand_uint64(void) { // Assuming RAND_MAX is 2^31. uint64_t r = rand(); r = r<<30 | rand(); r = r<<30 | rand(); return r; }
The long long data type makes handling 64 bit integers easy. In C language, an unsigned number over 32 bits cannot exceed the value of 4,294,967,295. You may find you are required to handle larger numbers and for this you need these numbers to be coded in 64-bit. However, this is not handled in the same way as an ordinary integer.
Concerning "So results are always 18 digits or 20 digits."
See @Thomas comment. If you generate random numbers long enough, code will create ones like 5, 11 and 33387. If code generates 1,000,000,000 numbers/second, it may take a year as very small numbers < 100,000 are so rare amongst all 64-bit numbers.
rand()
simple returns random bits. A simplistic method pulls 1 bit at a time
uint64_t rand_uint64_slow(void) {
uint64_t r = 0;
for (int i=0; i<64; i++) {
r = r*2 + rand()%2;
}
return r;
}
Assuming RAND_MAX
is some power of 2 - 1 as in OP's case 1073741823 == 0x3FFFFFFF
, take advantage that 30 at least 15 bits are generated each time. The following code will call rand()
5 3 times - a tad wasteful. Instead bits shifted out could be saved for the next random number, but that brings in other issues. Leave that for another day.
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=0; i<64; i += 15 /*30*/) {
r = r*((uint64_t)RAND_MAX + 1) + rand();
}
return r;
}
A portable loop count method avoids the 15 /*30*/
- But see 2020 edit below.
#if RAND_MAX/256 >= 0xFFFFFFFFFFFFFF
#define LOOP_COUNT 1
#elif RAND_MAX/256 >= 0xFFFFFF
#define LOOP_COUNT 2
#elif RAND_MAX/256 >= 0x3FFFF
#define LOOP_COUNT 3
#elif RAND_MAX/256 >= 0x1FF
#define LOOP_COUNT 4
#else
#define LOOP_COUNT 5
#endif
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=LOOP_COUNT; i > 0; i--) {
r = r*(RAND_MAX + (uint64_t)1) + rand();
}
return r;
}
The autocorrelation effects commented here are caused by a weak rand()
. C does not specify a particular method of random number generation. The above relies on rand()
- or whatever base random function employed - being good.
If rand()
is sub-par, then code should use other generators. Yet one can still use this approach to build up larger random numbers.
[Edit 2020]
Hallvard B. Furuseth provides as nice way to determine the number of bits in RAND_MAX
when it is a Mersenne Number - a power of 2 minus 1.
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
_Static_assert((RAND_MAX & (RAND_MAX + 1u)) == 0, "RAND_MAX not a Mersenne number");
uint64_t rand64(void) {
uint64_t r = 0;
for (int i = 0; i < 64; i += RAND_MAX_WIDTH) {
r <<= RAND_MAX_WIDTH;
r ^= (unsigned) rand();
}
return r;
}
If you don't need cryptographically secure pseudo random numbers, I would suggest using MT19937-64. It is a 64 bit version of Mersenne Twister PRNG.
Please, do not combine rand()
outputs and do not build upon other tricks. Use existing implementation:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With