What is the best way to seed srand()? [duplicate] - c

This question already has answers here:
Recommended way to initialize srand?
(15 answers)
Closed 9 years ago.
The way I learned was to initially seed the random number generator with srand(time(NULL)) and then use calls to rand() to generate random numbers. The problem with this approach is if I run my program multiple times in the same second, the random numbers generated will always be the same. What is a good way around this?

On POSIX systems, use clock_gettime to get the current time in nanoseconds. If you don't need a lot of bits, you can just forget the PRNG and use the low-order bits of the time as your random number directly. :-)

int pid ; // get it as per your OS
timeval t;
gettimeofday(&t, NULL);
srand(t.tv_usec * t.tv_sec * pid);
time gives you values based on second. gettimeofday is based on microseconds. So less chance of the same seed happening. Plus you are also using the process id.

If *nix, Why don't you read directly from /dev/random?
Also you can gather noise from other devices, like the keyboard, mouse or the CPU temperature.
You can use an accelerometer and use it to gather noise from sea waves. The Wind also produce noise.
I believe Glib provides a function, g_random_int() which produces random numbers equally distributed in a fast and portable way.
Or you can just read the numbers of temporal files in /tmp and use that number to feed srand() with a time.h function, or read the content of one file in /tmp.
You can read each file from /usr/bin or / and gather some food for srand().

Besides using time, another common way to seed your rand function is to use the process id of your program, since that is guaranteed to be unique.
The actual code is platform-dependent, but if you're on Windows, I believe you can use the function GetCurrentProcessId(), as in
srand(GetCurrentProcessId());

Beside inputting the time, you could add the CPU time to this, which I believe can be do with clock().
So it would look like this: srand(time() + clock()).

Related

Generating random numbers in C with different seed in every loop? [duplicate]

This question already has answers here:
using rand to generate a random numbers
(6 answers)
Closed 5 years ago.
Note: This post is not a duplicate of how to generate random numbers in C, it does not answer my question.
I have a function which is:
double generator(double * ran_i) {
srand(time(NULL));
return ran_i[rand()%1000];
}
which takes an array containing 1000 numbers, then I try to call:
for(i=0; i< 1000; ++i) {
printf("%lf", generator(ran[0]));
}
However in that loop it always gives me the same number. I figured out that time(NULL) does not change the seed fast enough. How can I change this seed faster or even better change it in every loop? Also I can only use libraries compatible with ANSI C standard.
I figured out that time(NULL) does not change the seed fast enough.
That would be accurate. time returns the current timestamp in seconds, so it changes once every second.
How can I change this seed faster ...
You would need a source of randomness. On POSIX you might use /dev/urandom, but that is of course not necessarily available to all platforms that support ANSI C.
So, the conclusion is that there is no API in ANSI C to access a purely random seed source, so getting a new, random seed faster than once a second is not feasible in ANSI C.
... even better change it in every loop?
Seeding a pseudo random number generator on every call is silly - don't try to do it. Just seed once, at the start of the program. (You can re-seed if you need to repeat a sequence).

Seeding random number generator for a batch of programs

So normally I use something like:
srand(time(0));
To get pseudo-randomness that changes with every program invocation. However, I'm now in a situation where I have a batch of programs that will all be starting at the same time and since time only changes every second, most of the time all of my programs start with the same seed.
What is a better strategy for seeding my RNG when I want a bunch of programs to start at once and all get different seeds?
Use srand(time(0) ^ getpid()) to permute your seed by a process-specific value. This will ensure different seeds for processes started within the same second. Take care to not use this for anything "important", e.g., cryptography or real money is involved.
The permutation is accomplished using the "exclusive-or" or XOR operator '^'. Because we know that two process running at the same time must necessarily have different process-ids, by xoring the response from time(0) with the current PID, we can get some assurance that two different processes won't have exactly the same seed.
Note that this is a very weak assurance as we are only twiddling a few bits. If the time were to increment by exactly one second and the process id were to increment by exactly one, in certain circumstances you would end up with identical seeds.
If you need truly distinct random number seeds, then you want to read 4 bytes from /dev/random and then use that as an integer to seed your RNG.
And again, PLEASE do not use this random number sequence for anything "important". And by important I mean anything more than a simple monte-carlo simulation or a game of rock-paper-scissors.
You can combine time(0) with some other program-specific value. For example, XOR it with a decent hash of the program name (argv[0] would normally suffice), or even just (preferably a hash of) the process id (if they're launched on the same host, otherwise XOR further with a hash of the hostname or IP). You could even go so far as to use a hash of an UUID.
Note: just xoring with the process id is pretty weak - if the second ticks over while the processes are starting, it could easily be that the bits flipped in the time value match the bits that differ between two of your process ids, leaving the generated seed identical. That said, put in an amount of effort commensurate with how much you have reason to care....
Maybe you need to use getpid() as well as some sub-second time (and perhaps whole second time too). Maybe make an MD5 hash of the values, and use that? Using getpid() guarantees that part of the data you're using will be unique to each process, but doesn't of itself give you very much randomness in your seed. Of course, using rand() is hardly guaranteed to be a good random number generator. You certainly can't use it for cryptography.

Is there a better function than rand()?

I have a program, in C, which creates an array of 1000 integers using a random number from 0-999 and then performs some sort of algorithm on that array. In order to test the algorithm's running time, I try running the program 10000 times, but every time I run it the array is the same for a few arrays and then it changes. I have used the srand() function to feed the seed with the current time, but it still does not help.
Is there an alternative solution to rand() or a way to fix this?
My function is:
void getarray(int *ptr1, int size, int option){
int n;
srand(time(NULL));
for(n=0; n<size; n++)
*(ptr1+n) = *(ptr2+n)= rand()%1000;
}
Thanks in advance!
You should only call srand once: on program startup.
Right now, if you call your function multiple times before time changes your sequence will be the same.
The lrand48() call tends to have a lot more state internally and a better pseudorandom number distribution.
However, note that you're reseeding with only 1-second granularity, so calls within the same second will generate the same sequence. Put your srand() call in main() or somewhere, once, instead of recalling it in getarray.
You should investigate very carefully if rand() is the better function for the job.
It varies by compiler and platforms but it is often implmented as a "Linear congruential generator" which are very convenient in terms of speed and memory usage but have poor statistical properties (i.e. you can tell if a long enough sequence has been generated by congruential random generator or if it's truly random).
In your use case (testing algorithm's speed) may be perfectly fine to use rand() as long the execution is not influenced by the statistical properties of the data. If rand() is a linear congruential RNG, number sequences show a pattern which means that at any given time it is not true that all the numbers are equiprobable. A nice example is in this wikipedia picture:
Your system might also have a RNG (e.g. /dev/random) and its associated functions but be aware that those are meant to produce few high quality random numbers and may be pretty slow to use. You might even run out of numbers and end up waiting for the system to collect more enthropy!
A simple, pretty fast RNG with statistical properties good enough for cryptography is ISAAC. Personally I use it whenever I need decent random numbers.
Another alternative is to use true random numbers as those generated by RANDOM.org or HotBits but it may be overkill in your case.
As a side note, RANDOM.ORG has a nice page on RNG with another example of "patterns" created by the PHP rand() function
First, call the seed function once, not in a loop.
Second, I suggest you either :
1) Switch to the random(3) function
2) Pick something from rand48 / lrand48
3) Read the number of desired bytes for /dev/random yourself.
Solution 1) is easy and somewhat portable. 2 need a bit of thinking, 3 is the most work, and the least portable.

trying to find a fully-random number generator

I work in C and i am trying(desperately) to make a random generator that not only generates
a different number every time i run the generator but also a different sequence every time i run the program.I tested almost everything i found online.I resulted in 2 good ways to make a good random generator.
The first one is to use a different seed every time.But this means that i have to use a different-random seed every time,a matter that i didn't solve at first.Here is what i am trying now but it's not truly random as i want:
int myrand(int random_seed){
random_seed = random_seed * 1103515245 +12345;
return (unsigned int)(random_seed / 65536) % 32768;
}
Every time i call the function i increase the seed by 1.
The second way is to use time.Time changes and this is randomness.I also tried many ways to implement this.My latest try is here:
Compiler error-Possible IDE error"undefined reference to gettimeofday error"
but i couldn't use the gettimeofday function because i work in Windows.Also in that question i didn't get any answers.
Could anyone give help me of how i can implement a random generator(probably using time) in C working in Windows?Or should i use Unix?
Seed your RNG with a good source of entropy.
Under unix, use /dev/random.
Under windows, use something like CryptoAPI - Windows equivalent of /dev/random
What you are asking for is not a random number generator, but how to use the random number generator already included in the C standard library.
All you need to do is seed it once at program startup:
srand(time(NULL));
That's all. It's portable and will give you a different sequence every time you run the program, given that at least one second has passed since the last time you've ran it.
There is no harm in seeding it again later, but no point in it either.
The C standard library has the header time.h (or ctime if you are using C++)(reference). The functions there will be supported in Windows and Unix.
I would recommend time() or clock() as seed for your random number generator.
An other way to get totally random input is the usage of the mouse position or other things influenced from outside.
There are many ways to implement prng but unfortunately none of them is real random number generator. time(NULL) is a good approach but I'm using "blum blum shub". It generates one bit random number
Since you're asking explicitly for a Windows solution I'd suggest to avoid time(NULL) or clock() as a seed for srand()since their granularity is very limited (ms). Instead you could use the result of the performance counter:
LARGE_INTEGER PerformanceCount;
QueryPerformanceCounter(&PerformanceCount);
srand(PerformanceCount.LowPart);
The increment rate of the frequency of QueryPerformanceCounter() can be obtained by a call to QueryPerformanceFrequency(). This typically increases at at least 1 MHz and sometimes even into the GHz range. Therefore it provides a fast changing source for the seed.
Edit: As understood from your earlier question also a gettimeofday() alike implementation won't give fine granularity. It may show the word tv_usec in its argument but on WIndows it will not provide microseconds granularity as it does on Linux systems.
quote:
to make a random generator that not only generates a different number every time i run the generator
Definitions of random do not include that concept. Rather the idea is that you have an equal chance of selecting any number, regardless of the number previously chosen. Which means it is theoretically possible to pick the same number twice.
If you are dealing a deck of cards then that meets your criterion of no duplicates. Using the deck dealing approach means keeping track of "used" numbers.
You should also be aware that PNRGs (pseudorandom number generators) are cyclic (periodic). After you have generated numbers, usually a large number, you then start all over again and repeat exactly the name sequence of numbers. The UNIX rand() function generates integers integers in the range [0, {RAND_MAX}] and has a period of 2^32
Really consider reading this short page:
See: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

How to 'randomize()' random numbers in C(Linux)?

Trying to generate random numbers in C, rand() doesn't generate different numbers each time i compile the code, can anyone tell me how to use srand() or tell any other method for generating.
In order to generate a sequence of pseudorandom numbers, the generator needs to be seeded. The seed fully determines the sequence of numbers that will be produced. In C, you seed with srand, as you indicate. According to the srand(3) man page, no explicit seeding implies that the generator will use 1 as a seed. This expains why you always see the same numbers (but do remember that the sequence itself is pretty random, with quality depending on the generator used, even though the sequence is the same each time).
User mzabsky points out that one way to get a seed that feels random to a human user is to seed with time. Another common method (which I just saw that mzabsky also points out - sorry) is to seed the generator with the contents of the system's random number generator, which draws from an entropy pool fed by things such as mouse movement, disk timings etc. You can't draw a lot of randomness from the system generator, as it won't be able to gather enough entropy. But if you just draw a seed from it, you'll have chosen at random a sequence of random numbers in your program. Here's an example of how to do that in C on Linux:
unsigned int seed;
FILE* urandom = fopen("/dev/urandom", "r");
fread(&seed, sizeof(int), 1, urandom);
fclose(urandom);
srand(seed);
In light of Conrad Meyer's answer, I thought I'd elaborate a bit more. I'd divide the use of random numbers into three categories:
Variation. If you use random numbers to create seemingly random or varied behavior in for example a game, you don't need to think very hard about the topic, or about choosing a proper seed. Seed with time, and look at some other solution if this turns out not to be good enough. Even relatively bad RNGs will look random enough in this scenario.
Scientific simulations. If you use random numbers for scientific work, such as Monte Carlo calculations, you need to take care to choose a good generator. Your seed should be fixed (or user-changeable). You don't want variation (in the sense above); you want deterministic behavior but good randomness.
Cryptography. You'll want to be extremely careful. This is probably out of the scope of this thread.
This is commonly used solution:
srand ( time(NULL) );
Execution of all C code is deterministic, so you have to bring in something that is different every time you call the srand. In this case it is time.
Or you can read data from /dev/random (open it just like any other file).
If you are using an OS that does not provide /dev/random then use something like what is shown below
timeval t1;
gettimeofday(&t1, NULL);
srand(t1.tv_usec * t1.tv_sec);
This piece of code can be ported easily to other OS.
To improve the seed- you can combine (maybe using MD5 or a checksum algorithm) time product shown above with a MAC address of the host machine.
timeval t1;
gettimeofday(&t1, NULL);
unsigned int seed = t1.tv_usec * t1.tv_sec;
unsigned char mac_addr[6];
getMAC(&mac_addr);
improveSeedWithMAC(&seed, mac_addr) ; // MD5 or checksum ...
srand(seed);
Be careful; the rand(3) manpage on linux notes that rand() implementations on some platforms do not give good randomness on the lower-order bits. For this reason, you might want to use a library to acquire real random numbers. Glib provides useful functions like g_random_int_range() which may better suite your purpose.

Resources