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

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).

Related

Random Number In C Independent Of Time

Is there a way to generate random numbers in c language independent of time.
The idea is that I want to generate an array of random numbers at a time,but since rand() method depends on time,all the values in the array are generated similarly.
rand() doesn't depend on time. People typically seed their pseudo-random number generator using the current time (through the srand() function), but they don't have to. You can just pass whatever number you want to srand().
If your random numbers aren't of a high enough quality for your purposes (libc's rand is notorious for its inadequacy), you should look at other sources of randomness. On most operating systems, you can get high-quality random data just by reading from /dev/random (or /dev/urandom), and the Windows API provides CryptGenRandom. There are also a lot of cross-platform libraries that provide high-quality PRNGS; OpenSSL is one of them.
rand() generates values sequentially (in a time-sequence), but does not depend upon time (as in "time of day"), unless you seed the generator with srand(time(NULL)). If you don't do this, it's dependent on 1 (one).
There's also rand_r() (POSIX) to return the value of the current seed. You could use these to coordinate multiple streams of random-numbers, by saving and restoring the appropriate seed values.
For a non-deterministic seed without using time(NULL) you'll probably have to resort to a system-specific source (/dev/random on unix).
At all costs don't do this, and proceed to use myrand() as a replacement for rand(). This will return the same value for each call during each clock second.
unsigned myrand() { // BAD! NO!
srand(time(NULL)); // re-seeding destroys the properties of `rand()`
return rand();
}
If you call srand(), it should be just once at the beginning of the program.
The sequential determinism of rand() is actually a very useful property for testing programs. What you get is an (almost-)random, but repeatable sequence. If you print out the seed value at the start of the program, you can re-use the same value to produce the same results (like if it doesn't work on that run).

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

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()).

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 unique is rand() in C?

I am using rand() for a 6 digit field which needs unique values. Am I doing it right?
What are the odds, rand() can give me similar values on consecutive or frequent calls?
It was unique when I used rand(). But, returned same number when I called srand(time(NULL)) or srand(clock()). Seems, like it's working opposite for me. Or is it?
As others have pointed out, uniqueness is not guaranteed. However you are probably seeing repeated numbers because you are using srand() and rand() incorrectly.
srand() is used to seed the random number generator. that means a series of calls to rand() after a call to srand will produce a particular series of values. If you call srand() with the same value then rand() will produce the same series of values (for a given implementation, there's no guarantee between different implementations)
int main() {
srand(100);
for(int i = 0; i<5; ++i)
printf("%d\n",rand());
printf("\nreset\n\n");
srand(100);
for(int i = 0; i<5; ++i)
printf("%d\n",rand());
}
for me this produces:
365
1216
5415
16704
24504
reset
365
1216
5415
16704
24504
time() and clock() return the time, but if you call them quickly enough then the value returned will be the same, so you will get the same series of values out of rand().
Additionally rand() is generally not a very good random number generator and using it usually means you have to transform the series of numbers to the distribution you actually need. You should find a different source of randomness and either learn the proper ways to produce the distribution you want or use a library that can do it for you. (for example one common method of producing a 'random' number between 0 and N is to do rand() % N but this is not really the best method.
C++ provides a much better random number library in <random>. It provides different PRNG algorithms, such as linear_congruential, mersennne_twister, and possibly even a cryptographically secure RNG (depending on the implementation). It also provides objects for producing a variety of distributions, such as uniform_int_distribution which should avoid the mistake make in rand() % N.
rand() returns values between 0 and RAND_MAX. Since it's a discrete uniform distribution, you have a probability of 1/(RAND_MAX+1) of repeating a number and therefore, uniqueness is not guaranteed.
srand(seed) initializes your random number generator so that the sequence of numbers obtained from rand() is the same every time given that you initialize it with seed every time.
In your example seed = time(NULL) which is the number of seconds elapsed from January 1, 1970 thus ensuring a different seed, and thus a different sequence of random numbers for every call to srand(time(NULL)) (assuming that it's not made within the same second).
Random numbers are random, not unique. Just like a situation with throwing dice when you can roll several sixes in a row, your rand can (and should) sometimes give you runs of identical numbers.
In order to make sure that the numbers are unique, build a set where you register each of the numbers that you have added already. When a random number comes up more than once, throw the second one away, and go for the next one.
What are the odds, rand() can give me similar values on consecutive or frequent calls?
The algorithm of rand is unspecified in C. So is the quality of the randomness of the numbers returned by rand.

How does the random number generator work in C?

I'm trying to generate random number between 0 and 40(inclusive).
So the code I Implemented is this-
y=rand()%41;
However everytime I click compile and hit Run. It outputs the same random numbers.
As in say for instance I ran this in a loop.
for(i=0;i<4;i++)
{
y=rand()%41;
printf("%d ",y);
}
Every single time, the output is the same 4 numbers. It always outputs 14,2,etc etc on the terminal. No matter what.
So my first question is, why is this happening?
and Secondly, how does the random number generator work in C?
I thought since I include time.h library, the numbers are generated through some standard algorithm using the system time. And since the system time is continuously changing, the numbers that are generated should also change every time I run the program.
rand() generates only pseudorandom numbers. This means that every time you run your code you will get exactly the same sequence of numbers.
Consider using
srand(time(NULL))
to get every time different numbers. In fact a possible implementation for rand is
next = next * 1103515245 + 12345;
return (UINT32)(next>>16) & RAND_MAX;
where next is defined as
static UINT32 next = 1;
Calling srand() has the effect of changing the initial value of next, thus changing the "next" value you get as result.
As for how it works, it depends. Many implementations use a Linear Congruential Generator, with different parameters.
The algorithm used for rand is unspecified by the C Standard,
By specification, if you don't call srand before a call to rand in your program, it is as if srand(1) was called: the seed value will be 1 at every execution of the program and the generated sequence will be always the same.
A common way to have different seeds for different executions of the program is to use a seed which depends on the current time like:
srand(time(NULL));
This is actually a FAQ on comp.lang.c. Here's the solution that they suggest:
(int)((double)rand() / ((double) RAND_MAX + 1) * N )
Where N is the ceiling of your range of random numbers. This is because the low order bits on bad C compilers are "shockingly non-random". This doesn't get around the need for using srand(). Note, however that srand( time(NULL) ) should be called outside of your loop... time() has a resolution of 1 second, so calling it inside of the loop will re-initialize your random number generator to the same seed many times in a row.
The need for this is probably largely historical, I'm sure that modern compilers probably don't have random number generators which emit really bad random numbers, but I remember writing a program using the Borland C compiler which would cycle through about 5 numbers when I used rand() % 41 repeatedly.
Reason is that rand() is using the same seeding everytime you run. You have to seed it yourself. srand ( time(NULL) );` is usually used to initialize random seed.
It is generated by an argument passed seed. To generate different numbers add this before calling the rand() function:
srand (time(NULL));
This generates a new random seed.
You should have this library: #include <time.h> And if you still have an error use this one as well: #include <stdlib.h>

Resources