Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate random 64-bit unsigned integer in C

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.

like image 217
Erdi İzgi Avatar asked Oct 08 '15 08:10

Erdi İzgi


People also ask

How do you generate a 64-bit random number?

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.

What is 64-bit unsigned integer?

uint64. A 64-bit unsigned integer. It has a minimum value of 0 and a maximum value of (2^64)-1 (inclusive).

Which system is used to generate random unsigned integers?

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.

How to generate a random number in C program?

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.

How many bits does it take to generate a random number?

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

How to generate 64-bit random value from 32 bit?

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

How to handle 64 bit integers in C language?

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.


2 Answers

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;
}
like image 110
chux - Reinstate Monica Avatar answered Sep 17 '22 12:09

chux - Reinstate Monica


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

like image 38
Stas Avatar answered Sep 20 '22 12:09

Stas