IPSC Logo

Internet Problem Solving Contest

IPSC 2007

Problem K – Know Your Crypto

Some random musings on rand()

Do all C compilers have the same rand() function?

No. The standard does not define a fixed implementation.

How can I tell two machines have the same rand() function?

The simplest test would be to print out some random values for a fixed seed. If they match, you most probably have the same implementation. E.g., you may try this piece of code:

#include <stdio.h>
#include <stdlib.h>

int main() {
  int i;
  srand(47);
  for (i=0; i<10; i++) printf("%d\n",rand());
  return 0;
}

What does that code output on your machine?

The output is the following sequence:

1773134790
1924001091
438623483
50210213
809830442
761766184
2023073002
729207936
708098155
2037448065

I don't have a C compiler that uses the GNU C library. Can I implement the same pseudo-random generator on my machine?

The GNU C library is distributed under the GPL. You can just download it and look at the implementation. (It's in the directory stdlib, look for filenames containing the substring rand.)

Alternately, we even provide our own reference implementation below. The ipsc_srandom and ipsc_random functions are equivalent to the GNU C library functions srand and rand we used.

#define GENERATOR_DEG 31
int32_t ipsc_random_table[GENERATOR_DEG] = {
 -1726662223,   379960547,  1735697613,  1040273694,  1313901226,  1627687941,
  -179304937, -2073333483,  1780058412, -1989503057,  -615974602,   344556628,
   939512070, -1249116260,  1507946756,  -812545463,   154635395,  1388815473,
 -1926676823,   525320961, -1009028674,   968117788,  -123449607,  1284210865,
   435012392, -2017506339,  -911064859,  -370259173,  1132637927,  1398500161,
  -205601318,
};
int front_pointer=3, rear_pointer=0;

int32_t ipsc_random() {
  int32_t result;
  ipsc_random_table[ front_pointer ] += ipsc_random_table[ rear_pointer ];
  result = ( ipsc_random_table[ front_pointer ] >> 1 ) & 0x7fffffff;
  front_pointer++, rear_pointer++;
  if (front_pointer >= GENERATOR_DEG) front_pointer = 0;
  if (rear_pointer >= GENERATOR_DEG) rear_pointer = 0;
  return result;
}

void ipsc_srandom(unsigned int seed) {
  int32_t i, dst=0, kc=GENERATOR_DEG, word, hi, lo;
  word = ipsc_random_table[0] = (seed==0) ? 1 : seed;
  for (i = 1; i < kc; ++i) {
    hi = word / 127773, lo = word % 127773;
    word = 16807 * lo - 2836 * hi;
    if (word < 0) word += 2147483647;
    ipsc_random_table[++dst] = word;
  }
  front_pointer=3, rear_pointer=0;
  kc *= 10;
  while (--kc >= 0) ipsc_random();
}