Gautam
Gautam

Reputation: 1772

Simple random number generator in C isn't working

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

int main(int argc, char** argv) {


    srand(time(NULL));
    int r = rand();

    printf("%d\n", r);

    return (EXIT_SUCCESS);
}

When I run this code snippet repeatedly in the space of a few seconds, I get an increasing series of number such as 213252683, 213975384, 214193875, 214445980. It looks to me like I'm just printing out the system time - that hypothesis seems to be confirmed when I add the line printf("%d\n", time(NULL)); to the code. What am I doing wrong? I'm running on Mac OS X 10.6.1 (Snow Leopard), but I'm only using Standard Library functions, so it shouldn't make a difference. Thanks!

Upvotes: 1

Views: 2783

Answers (5)

Luke Walsh
Luke Walsh

Reputation: 281

You should use random() instead of rand(). It is superior to rand() in every way, and it is also included in stdlib.
Try the following code:

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

int main(int argc, char** argv) {
int r = random();
printf("%d\n", r);
return (EXIT_SUCCESS);
}

Upvotes: 0

Seb Fanals
Seb Fanals

Reputation: 645

In case it helps I generally use it that way:

int rand_between(int min, int max)
{
  static int flag = 1;
  FILE *urandom;
  unsigned int seed;

  if (flag)
    {
      flag = 0;
      if (!(urandom = fopen ("/dev/urandom", "r")))
      fprintf(stderr, "Cannot open /dev/urandom!\n");
      fread(&seed, sizeof(seed), 1, urandom);
      srand(seed);
    }
  return ((int)rand() % (max - min)) + min;
}

To get a random uppercase letter:

char letter = (char)rand_between('A', 'Z');

Upvotes: 0

Aaron Dufour
Aaron Dufour

Reputation: 17505

The random number generator differs widely, so this will be difficult to reproduce on other machines. It looks like the first number from your implementation is just the seed value. On mine, for example, the first number appears to be linearly related to the seed. Generally, you will call srand once in a program, and rand many times, and successive calls will get more random-looking results. If you want to avoid this problem, it would be reasonable to do:

srand(time(NULL));
rand();
int r = rand();

printf("%d\n", r);

The first rand call makes sure the seed doesn't get returned, and the next one should pick up something that appears more random. Note that if you run the program twice in a short enough time span (such that time(NULL) is the same in both runs) you will get exactly the same results. This is definitely to be expected - use a different seed value (pid + time might be a good start, or just a higher-resolution time) if this is a problem.

Upvotes: 1

sleske
sleske

Reputation: 83599

When I run this code snippet repeatedly in the space of a few seconds, I get an increasing series of number such as 213252683, 213975384, 214193875, 214445980.

I cannot reproduce this. On my system (Debian Linux) I get numbers that are not ordered. Also, the results are not the same as what you get when you print time(NULL).

This is as it should be: You are seeding the random number generator with the current time (in seconds). Thus as long as the time (down to seconds) is the same, your program will print the same result.

What am I doing wrong?

Well, that depends on what you want. If you want random numbers for every run, you need a better source of randomness. You could try functions like gettimeofday, which have higher resolution (typically ms, I believe). Also, mix in other sources of randomness, like the ID of your process.

In most programs, the effect you see is no problem, because typically srand() is only called at the start, and then rand() returns a different number on every call.

If you want "secure" (i.e. unpredictable) random numbers, that's a whole other game. See e.g. Wikipedia for an overview.

Upvotes: 0

Imp
Imp

Reputation: 8609

Pseudorandom numbers are generated as a chaotic sequence derived from an initial seed. srand initializes the randomness by setting this seed. Apparently, the first random number in the sequence is the seed itself - which is the time() value you set.

This is the reason, why the right way to generate a random sequence is to call srand() only once at the beginning of the program, and then only call rand() (well, maybe until the sequence starts looping, which shouldn't happen too soon, but that depends on the generating function). Calling srand() too often will, as you have seen, deteriorate the randomness.

Upvotes: 3

Related Questions