I have the following c code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[]) {
srand(time(NULL));
printf("%d\n", (int)random());
return 0;
}
To my understanding, this should print a different random number every time I execute the program because the random seed is dependent of the system time.
But every time run the program, I get exactly the same output:
1804289383
I still get the same output when I put custom values as argument for srand:
srand(1);
Or
srand(12345);
Does anyone have an Idea why this happens? Maybe it is because of my operating system (Mac OS 10.10.3)? Or the compiler I use (gcc)?
Are there simple alternatives?
The standard random number generator in C is rand(), which can be seeded with srand(seed).
There is a second random number generator, random(). This random generator can be seeded with the function srandom(seed). (These two generators use separate states, even if they share the same implementation.)
So just pick the correct pair of seeding and RNG functions.
Well, your problem here is due to multiple way of making random numbers in C with the standard libraries.
Basically, there is two sets of functions to generate a random number :
From the rand(3) manual:
#include <stdlib.h>
int rand(void);
int rand_r(unsigned int *seedp);
void srand(unsigned int seed);
From the random(3) manual:
#include <stdlib.h>
long int random(void);
void srandom(unsigned int seed);
char *initstate(unsigned int seed, char *state, size_t n);
char *setstate(char *state);
You should just pick the one that suit the best your need.
I invite you to further read those manuals for more information ;-)
Related
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[]) {
srand((unsigned)time(NULL));
printf("%d\n", rand()%100+1);
printf("%d", rand()%100+1);
return 0;
}
I've run this many times and each time the first value just increased steadily, like 2 5 9 17 24 30 ..... 91 97 3 7 12 (but the value is always different). Strangely, the second value performed normally, what could be the reason?
I'm using Dev-C++ and TDM-GCC 4.9.2
You're pretty much right, I also don't know the exact or correct reason of this happening.
But I fixed this issue with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
int main(int argc, char *argv[])
{
srand(time(NULL));
for (;;) // running infinitely here until program's interrupted
{
printf("%d\n", rand() % 100 + 1);
printf("%d", rand() % 100 + 1);
printf("\n---\n");
sleep(1);
}
return 0;
}
If you put srand(time(NULL)) outside the infinite loop and everything else inside it, it'll work correctly. After this, you'll get both values changed randomly in each iteration rather than just increasing (the first value).
Your root cause is likely that C's old random number generator is not really that good. In my mind it's primary use cases are when quality is not important or you need the ability to repeat "random number" series to assure test results, and the like, can compare well over time. These "pseudo random number generators" have forever been a sore spot to projects needing good random numbers.
If you need true good stuff you can obtain random numbers using:
Entropy based features found on most popular operating systems, like the /dev/urandom family of random devices on unix-like systems. Microsoft Windows has something as well but I've forgotten it.
Internet random number services like random.org (obviously not for high-volume numbers). They have APIs so programs can automate the experience, which would be educational but be sure to follow the guidelines.
Hardware random number generators (search for: usb random numbers) if you really want quality or quantity.
Historically using just the low-order bits of rand() values tends to amplify the defects, which may help get what you saw. I've posted a second answer that goes into the nuts and bolts of improving on the performance of rand().
Try run
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[]) {
unsigned i;
for (i=0; i<100; ++i) {
srand(i);
printf("%d\n", rand()%100);
}
return 0;
}
If you get a pure increasing list, then it's because your randomness returns seed at the first run.
To fix it, call a rand() just after srand and ignore its value. It'll somehow seem to improve the randomness.
On top of the defective nature of most rand() implementations mentioned in my first answer on broader issues of random numbers there is also a subtle problem in your %100. As RAND_MAX is usually a power of two, say 32767, using just the last two digits will slightly favor lower values as there will be the potential of missing 68-99 some some calls. To get uniform 00-99 distributions you would need to go to 32799, which is not going to happen.
A better solution would be to do something to get a random value from 0.0 to 0.999999... in a way that uses all bits and then expand on that:
//untested code alert:
double rand01 = (double)(rand()%RAND_MAX) / (double)RAND_MAX; // get zero up to but not including one
printf( "%d\n", 1 + int(100.0 * rand01) );
This uses all the available bits in the returned random numbers.
Software generated random numbers have always been a pain-point in computers.
This question already has answers here:
srand() — why call it only once?
(7 answers)
How to use function srand() with time.h? [duplicate]
(5 answers)
Closed 4 years ago.
#include <stdio.h>
#include <stdlib.h>
int main( void){
int x = rand()%100;
printf("%d\n", x);
return 0;
}
The code above generates a random number correctly. Is this correct? But, other sources always include library and srand(time(NULL)). Why do we have to include include library and srand(time(NULL))? Are there any reasons to include?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main( void){
srand(time(NULL));
int x = rand()%100;
printf("%d\n", x);
return 0;
}
Because if you run this code many times, you will get the same result! (also, rand() return the same result in each run). Hence, you can initialize the seed of random in each run of the code to get a different random result by srand. Using time(NULL) to set a different seed of random through srand.
srand is a random number generator function which will randomize the number produced by rand function.
Imagine you have a (huge) library with (huge) books filled with (apparently random, but fixed) numbers.
When you do rand() you get the current number on the current book and advance to the next.
When you do srand(<number>) you select the book rand() will use from that point forward.
time(NULL) return the number (after conversion) of seconds since about midnight 1970-01-01. That number changes every second, so using that number to "select a book" pretty much guarantees a new sequence of "random" numbers every time your program runs.
If you don't select a book, the rand() function takes numbers from book #1 (same as srand(1)).
Having fixed random numbers may be useful in certain situations. For example, you want to test different functions with the same data.
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
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.
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.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
calling rand() returning non-random results
In my workshop I need to takes 2 different random numbers but I get 2 same random number.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int random1_6(){
int k;
srand(time(0));
k=((rand()%6)+1);
return k;
}
int main(void){
int a,b;
a=random1_6();
printf("%d.\n",a);
b=random1_6();
printf("%d.\n",b);
return 0;
}
How to get 2 different random number?
A non-cryptographic random number generator (RNG) is not truely random but it generates random-like numbers based on a seed.
What you do is initializing the RNG with the same seed two times, so you get the same results. Seed the RNG just once, e.g. at program start, and you will get random-like different results.
Edit: a code like follows should work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int random1_6(){
return ((rand() % 6) + 1);
}
int main(void){
int a,b;
srand(time(NULL));
a = random1_6();
printf("%d.\n",a);
b=random1_6();
printf("%d.\n",b);
return 0;
}
Don't do srand(time(0)); on every call. Only call it once.
You must initialize the random number generator seed with srand() only once : upon each call you are re-initializing the RNG with the same seed since is it most likely that the two subsequent calls to time(0) will return the same timestamp (seconds-level precision), hence rand() will return the same number twice.
If you call srand() only once at the beginning of your program (in the main() entry-point), then every call to rand() will return a different number.
You always initialize the random number generator with the same seed, so you'll get the same random sequence, it is pseudo random anyway. Typically you will only want to call srand once in the beginning to initialize the generator.
Also, you only have 6 different possible outcomes, so it is perfectly legitimate to get same number twice, there is 1/6 chance for that.
#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!
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.
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.
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.
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');
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);
}