How does the random number generator work in C? - 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>

Related

Generate random numbers based on seed value

Can someone explain to me what seed value is? For example I have this code:
int MIN=0;
int MAX=100;
srand((unsigned) time(NULL));
srand(2020);
int num = (int)(rand() / (RAND_MAX + 1.0 + MIN) * MAX);
I am required to use a seed value of 2020 to generate numbers between 0 to 100. I checked everywhere but seems like there is no tutorial that explains what seed value is, and how the code should change from the default seed value. Line 3 of my code assumes the default seed value, so it does not work with a seed value of 2020. Also, MAX is 100, and MIN is 0.
Thanks in advance!
The pseudo-random number generator is initialized using the argument passed as seed. For every different seed value used in a call to srand, the pseudo-random number generator can be expected to generate a different succession of results in the subsequent calls to rand.
http://www.cplusplus.com/reference/cstdlib/srand/
Then calling rand() will return a pseudo-random number in the range of 0 to RAND_MAX.
If you want rand() to produce different random numbers, ensure you are not calling srand(2020) each time you are calling rand(). As you only need to seed the random number generation once.
The seed has 2 usages. The most common one is to start a random generator with a different value. It matters when you want to produce a random value for a crypto algorithm. When you start the program, you do not want to use the same value on each run...
The other usage is to generate a reproducible pseudo-random sequence. It matters when you want reproducible tests, or when you want to exchange with others with random data but want all to use the same sequence. It is very often used in tutorials to have a consistent sequence that the user will be able to reproduce when following the tuto. It is also used by teachers because it is easier to see if students have found the correct result (if every student uses a different sequence, all results would be different)
The rand function generates some sequence of numbers. (The sequence is calculated but is intended to serve as if the numbers were random, so they are called pseudo-random.) By itself, it will always generate the same sequence of numbers in a program. We use srand to choose which sequence of numbers it generates. (Most commonly, rand generates a cycle of the same numbers, if called enough times, and srand merely chooses where in that cycle we start.)
So, you call srand to set the starting point of the sequence for rand. The value you pass to srand is any unsigned int value. In the C standard, there is no specified meaning for the value. You just give srand a number like 1 to get one sequence, 2 to get a different sequence, 3 to get another sequence, and so on. You have no other control over the actual values generated; setting the seed to some particular value does not guarantee the first rand call will return any particular documented value.
The C standard also does not specify any method for calculating the numbers in the sequence. Each C implementation may choose its own method. Some C implementations use bad methods, in which the numbers are not very random-like at all, and some patterns can be easily observed. (For this reason, it is often recommended to use alternatives, like Unix’s srandom and random.)
When a program is being debugged or is being used as a class assignment, it is common to call srand with a fixed value, like srand(2020). This results in rand generating the same numbers each time. That makes it easier to debug the program or to check the results of student programs. When varying sequences of numbers are designed, it is common to call srand with srand(time(NULL)). Assuming the time is available (time(NULL) may return −1 for an error), this causes the program to use different sequences at different times. (Commonly, the value of time as an integer changes once per second, but this can vary depending on the C implementation.)
In C, srand takes a seed that determines the sequence of numbers rand will generate (also known as pseudorandom numbers), as long as the program doesn't change and the program uses the same implementation of rand and srand.
In C, srand and rand can't be used to create a reproducible sequence of pseudorandom numbers, because the standard that defines the C language doesn't specify what that sequence is, even if the seed is given. Notably, rand uses an unspecified pseudorandom number algorithm, and that algorithm can differ between C implementations, including versions of the same standard library. It's not the "compiler", the "system", or the "architecture" that decides which implementation of rand and srand is used. See also these questions:
How predictable is the result of rand() between individual systems?
Does Python have a function to mimic the sequence of C's rand()?
Why is the use of rand() considered bad?
To generate a random number with a specific seed use srand to set the seed for one-time only.
Then use rand to generate the random number. The default range is between 0 and RAND_MAX (RAND_MAX = 32767).
To define the maximum number just override RAND_MAX via precompiler statements (Side effects included) or use Modulo %.
Override RAND_MAX
#ifdef RAND_MAX
#undef RAND_MAX
#define RAND_MAX 100
#endif
Use Modulo
srand(2020);
int random_number = rand() % 100;

Does rand() indeed produce a random value when the random number generator has been seeded?

I know that in order to avoid repeating the same output of the rand() function a pseudo-random number generator must be seeded with the srand function. That means, if I try say srand(1), the output of the rand() will be one value, if I try srand(2), the output will contain another value. But when I try the first argument again like srand(1), the value will be the same as in the first output. This issue made me think that all random values would be predictable in some way. Is it possible to have different output for the same seed (say if I try the same seed tomorrow)? Or are random values predictable indeed?
With the traditional definition of a pseudorandom generator, if you know what the generator has been seeded with, then the sequence of output values is completely determined and not random. This means that if you knew the seed for a random generator, then you could predict every single output that generator would produce from that point forward. (A good random number generator is one where seeing a sequence of outputs of the generator does not let you easily reverse-engineer what the random seed is or predict other values.)
I seem to remember reading a while back that, a while back, some popular poker websites were not doing a good job choosing their random seeds. Some people figured out that you could input the pattern of cards you were seeing, and the system could then reverse-engineer the random seed and let you predict all the future cards. Oops. These days, we have cryptographically secure pseudorandom generators based on encryption routines that, at least when it comes to what's known in the open literature, can't be predicted even if you have gigabytes of random bits of output from the generators.
If you do need to get something that really isn't predictable - that is, you want to get a bunch of truly random bits - you'll need to use something other than a pseudorandom number generator. Most operating systems have some mechanism in place to generate values that do appear to be truly random. They might, for example, look at how long it takes for different capacitors to discharge on the motherboard, or factor in timing information from a clock, or see how the user interacts with the keyboard, etc. These data can be fed into something called an entropy accumulator that slowly builds up more and more random bits. If you need a value that's truly random and can't be predicted in advance, you can check your particular OS for the mechanism used to get data from the entropy accumulator. (You can read from /dev/random on UNIX-style machines, for example.)
Often, pulling data from the entropy accumulator takes time, since the computer has to wait long enough for enough different sources to mix together to give you back high-quality random data. A common strategy, therefore, is to use the entropy accumulator to get a high-quality random seed, then "stretch" the randomness by using it as the seed of a strong pseudorandom generator.
Here is the language of the C Standard:
7.22.2 Pseudo-random sequence generation functions
7.22.2.1 The rand function
Synopsis
#include <stdlib.h>
int rand(void);
The rand function computes a sequence of pseudo-random integers in the range 0 to RAND_MAX
The rand function is not required to avoid data races with other calls to pseudo-random sequence generation functions. The implementation shall behave as if no library function calls the rand function.
Returns
The rand function returns a pseudo-random integer.
Environmental limits
The value of the RAND_MAX macro shall be at least 32767.
7.22.2.2 The srand function
Synopsis
#include <stdlib.h>
void srand(unsigned int seed);
The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.
The srand function is not required to avoid data races with other calls to pseudo-random sequence generation functions. The implementation shall behave as if no library function calls the srand function.
Returns
The srand function returns no value.
In other words, rand() returns a pseudo-random sequence of integers between 0 and RAND_MAX. The sequence is not random, it is predictable for every value passed to srand(), including if srand() is never called.
In order to try and get different sequences for successive runs of the program, srand() can be called with a rapidly varying value, such as the return value of clock(). Note that calling srand(time(NULL)) will produce the same sequence for multiple runs of the program during the same second.

Is it possible to increase the refresh speed of srand(time(NULL)) in C?

I am asking to see if there is a way of increasing the speed the srand(time(NULL)); function "refreshes"? I understand srand() produces a new seed according to time (so once a second), but I am looking for an alternative to srand() that can refresh more often than 1 second intervals.
When I run my program it produces the result it is supposed to, but the seed stays the same for essentially a second, so if the program is run multiple times a second the result stays the same.
Sorry for such a simple question, but I couldn't find an answer specifically for C anywhere online.
You could try fetching a seed value from some other source. On a unix system, for example, you could fetch a random four-byte value from /dev/random:
void randomize() {
uint32_t seed=0;
FILE *devrnd = fopen("/dev/random","r");
fread(&seed, 4, 1, devrnd);
fclose(devrnd);
srand(seed);
}
srand(time(NULL)); is not a function, it is rather two functions: time() which returns the current time in seconds since the epoch; and srand() which initialises the seed of the random number generator. You are initialising the seed of the rendom number generator to the current time in seconds, which is quite a reasonable thing to do.
However you have several misconceptions, you only actually need to run srand once, or at most once every few minutes, after that rand() will continue to generate more random numbers on its own, srand() is just to set an initial seed for rand to start with.
Second, if you really do want to do this, while I don't see why you would you could use a function that returns the time to a higher precision. I would suggest gettimeofday() for this purpose.
Under Windows you can use GetTickCount() instead of time(). It changes on 50ms interval (if remember correctly).
I had the same issue, I found a easy fix with a high resolution clock.
#include <chrono>
#include <random>
int main() {
long long t1 = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::srand((unsigned int)t1);
}

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

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.

Resources