5

This is most likely a machine dependent issue but I can't figure out what could be wrong.

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

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

  srand(time(NULL));
  int r1 = rand();
  int r2 = rand();
  printf("%d %d\n", r1, r2);
}

I compile the above piece of code using

gcc randd.c

Then running it a few times manually and the first numbers seem incredibly similar while the second ones seem random:

1025720610 1435057801
1025737417 1717533050
1025754224 2000008299
1025771031 134999901
1025787838 417475150

This first call to rand() seems strongly co-related to the time and is strictly increasing as time passes. Any ideas as to why this occurs or how to resolve it?

This happens on OSX 10.11

jww
  • 97,681
  • 90
  • 411
  • 885
ᴘᴀɴᴀʏɪᴏᴛɪs
  • 7,169
  • 9
  • 50
  • 81
  • What system shows the problem? `printf("%d\n", rand());` might show the problem a bit more clearly. I'd expect to get the same output if the program is run twice within 1 second, but you're getting (slightly) different results each time. Please verify that the code you've shown us is *exactly* the code you've compiled and run. – Keith Thompson Feb 22 '17 at 00:01
  • 2
    Possible duplicate of [srand(time(NULL)) generating similar results](http://stackoverflow.com/questions/6668282/srandtimenull-generating-similar-results) – Emil Laine Feb 22 '17 at 00:03
  • @KeithThompson I've posted a screenshot with the exact code and commands I'm performing – ᴘᴀɴᴀʏɪᴏᴛɪs Feb 22 '17 at 00:22
  • Please don't post images of code. Copy-and-paste your code into the question *as text*. The problem is based on the values returned by `rand()` we only need to see those values, which are integers. Something like this: `srand(time(NULL)); printf("RAND_MAX = %d, rand() = %d\n", RAND_MAX, rand());`. In your modified program, you're calling `rand()` twice. It's likely that the *first* value returned by `rand()` is the problem. And again, what system are you using? – Keith Thompson Feb 22 '17 at 00:26
  • @KeithThompson This is on OSX 10.11 – ᴘᴀɴᴀʏɪᴏᴛɪs Feb 22 '17 at 00:33
  • It looks like value returned by the first call to `rand()` is strongly correlated to the seed somehow, and the second is not. Focus on that: `int r1 = rand(); int r2 = rand(); printf("%d %d\n", r2);`. Forget the floating-point stuff. Include the full text of the program and its output in your question. Also, tell us what OS you're using *in the question*. Assume that nobody will see these comments. – Keith Thompson Feb 22 '17 at 00:33
  • 1
    @KeithThompson Edited – ᴘᴀɴᴀʏɪᴏᴛɪs Feb 22 '17 at 00:43
  • 1
    @tuple_cat not a duplicate , you would expect the numbers to either be identical or completely different. not share a common initial sequence. – M.M Feb 22 '17 at 02:31
  • is this the exact code? E.g. you didn't use `random()` instead of `rand()` ? – M.M Feb 22 '17 at 02:33
  • @M.M Yes this is exact, I've copy-pasted it straight into the question. At this point this seems to be a deficiency in my c standard lib – ᴘᴀɴᴀʏɪᴏᴛɪs Feb 23 '17 at 01:08
  • Please do not edit your question such that it invalidates existing answers. Instead, create a new question. – Matt Feb 28 '17 at 13:49

2 Answers2

2
  1. rand() is quite bad, avoid it if possible. In any good RNG the first values will be indistinguishable from random even when the seed is close (hamming distance). In rand this is not the case.
  2. If you must use rand then seed it, preferably with something higher entropy than time, and call rand() multiple times instead of reseeding-calling-reseeding.

For example of 2, consider:

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

int main(int argc, char** argv) {
  int t=time(NULL);
  srand(t);

  for(int i=0; i < 10; i++) {
    float r = (float)rand()/(float)(RAND_MAX);
    printf("%f\n", r);
  }
}

With the result:

0.460600
0.310486
0.339473
0.519799
0.258825
0.072276
0.749423
0.552250
0.665374
0.939103

It's still a bad RNG but at least the range is better when you allow it to use the internal state instead of giving it another similar seed.

Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166
  • 1
    Something like time xor pid, for example, is a *somewhat* better seed, but still very predictable. Really use `/dev/urandom` (or whatever the Windows equivalent is). – Schwern Feb 22 '17 at 00:16
  • `rand()` is not inherently bad. Some implementations of `rand()` are bad. – Keith Thompson Feb 22 '17 at 00:28
  • 1
    @KeithThompson From a security standpoint, that `rand`'s specification is so broad and implementation is so unpredictable makes `rand` inherently bad. – Schwern Feb 22 '17 at 00:31
  • @Schwern: Who said anything about "security standpoint"? There's absolutely nothing bad about `rand()`. There are just some applications for which it is suitable. And no, there's no need to somehow "avoid" `rand()`. – AnT stands with Russia Feb 22 '17 at 00:45
  • WRT avoiding: Using my, admittedly unexplained, definition of "good" I'd say I don't know if any good implementation of rand. It isn't only about security but also period and number of possible random streams which is limited by the seed size. – Thomas M. DuBuisson Feb 22 '17 at 00:51
  • 1
    @AnT it's hard to imagine an application for `rand()` that is suited by the output OP got – M.M Feb 22 '17 at 02:31
  • @M.M: Frankly, I don't see the problem. For a generator like `rand()` the only thing that's expected from it is a uniform coverage of the target range and absence of trivial patterns in each post-`srand` session. I don't see any problems with that in the OP's example. – AnT stands with Russia Feb 22 '17 at 18:04
  • I agree, there's nothing at all wrong with the user's `rand()`, he just doesn't understand how to use it. – Lee Daniel Crocker Feb 22 '17 at 20:39
1

This is exactly what you should expect. There's no such thing as "a random number". There are only sequences of numbers with a random distribution. The rand() function generates such sequences, but you're not giving it a chance to, because you keep re-seeding it. The first number generated by rand() may very well be just some function of the seed, or the seed itself. Some rand() functions might hash the seed to hide this, but that doesn't really make them any better, because the contract of rand() is to produce a random sequence.

If you need a sequence of random numbers that survives running multiple programs, you'll have to do something like (a) Write a program that calls srand() once, then calls rand() many times, and have your other programs ask for random numbers from that program over IPC; (b) Use something like /dev/urandom; (c) Use something like random.org.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55