Generate random numbers based on seed value - c

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;

Related

Summing a list of random numbers always gives the same result. Why? [duplicate]

I quite like being able to generate the same set of pseudo-random data repeatedly, especially with tweaking experimental code. Through observation I would say that rand() seems to give the same sequence of numbers each time*.
Is it guaranteed to do this for repeated executions on the same machine / for different machines / for different architectures?
*For the same seed obviously.
Yes, given the same environment for the program. From the C standard §7.20.2.2/2,
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.
Of course, this assumes it is using the same implementation detail (i.e. same machine, same library at the same execution period). The C standard does not mandate a standard random number generating algorithm, thus, if you run the program with a different C standard library, one may get a different random number sequence.
See the question Consistent pseudo-random numbers across platforms if you need a portable and guaranteed random number sequence with a given seed.
It is guaranteed to give the same sequence for the same seed passed to srand() - but only for the duration of a single execution of the program. In general, if an implementation has a choice in behaviour, there is no specific requirement for that choice to remain the same across subsequent executions.
It would be conforming for an implementation to pick a "master seed" at each program startup, and use that to perturb the pseudo-random number generator in a way that is different each time the program starts.
If you wish for more determinism, you should implement a PRNG with specific parameters in your program.
No.
The C standard says:
If srand is then called with the same
seed value, the sequence of
pseudo-random numbers shall be
repeated.
But nowhere does it say what the sequence of pseudo-random numbers actually is - so it differs across implementations.
The only guarantee made is that rand() will give the same sequence of numbers for a given seed for a given implementation. There's no guarantee that the sequence will be the same across different machines or different architectures - and it almost certainly won't be.
If you need to use the exact same set of pseudo-random numbers for experimental purposes, one thing you could do is to use srand to generate a long sequence of random numbers and write them to a file/database. Then, write a portable "random number generator" function that returns values sequentially from that file. That way, you can be assured that you are using the same input data regardless of the platform, srand implementation, or seed value.
When switching to a different machine/runtime/whatever you might be out of luck. There is another possible choice the drand48 family of functions. These are normalized to use the same algorithm on all machines.
If you are in a UNIX/Linux enviroment you can see the drand48() and srand48() at your man pages if you are not you can see online manuals for the C Language.
The prototypes can be found at /usr/include/stdlib.h .
The first one use the Linear Congruential Method that is frequently used in Simulations.
If you provide the same seed to srand48() i.e. srand48(2) and then put the dran48() in a for loop then the sequence will be the same every time.
i.e.
include stdio.h
include stdlib.h
double drand48();
int main(void){
int i;
double rn;
srand48(2);
for(i=0; i<10; i++){
randNum = drand48();
printf("%.6l\n", randNum);
return 0;
}

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.

Does C's rand() have to be random?

I was trying to get some info on the specification and implementation of rand() in C, and I can't find much information. As a matter of fact, I can't find anything apart from:
rand() does not advance between function calls
same seed always results in same numbers
the random numbers are between 0 and RAND_MAX
Notably, none of these things require randomness. Specifically, I don't see anything that prohibits this implementation:
int randval = 0;
void srand(unsigned int seed) {
randval = seed;
return;
}
int rand() {
return randval++;
}
This seems somewhat unrandom. Is there a bit of standard I'm missing?
(Also, is is bad to seed rand() with time(), then seed ISAAC with rand()?)
Not only it does not have to be random, it must not be random, because it must be completely deterministic:
§7.22.2.2/2:
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.
If you need true randomness—for any cryptographic purposes you do—use /dev/random on Linux (and most other unices) and CryptGenRandom on Windows.
If you are instead interested in how well the pseudo-random sequence resembles a random one, that is how much it is statistically random, see #Story Teller's answer.
While notes in the C standard are not normative, it does say this:
7.22.2.1 The rand function / note 295
There are no guarantees as to the quality of the random sequence produced and some implementations are known to produce sequences with distressingly non-random low-order bits. Applications with particular requirements should use a generator that is known to be sufficient for their needs.
So you are correct that a completely lazy implementation of the standard library can look like this. It's not bad to seed rand with time, it's as good as any other seed, and provides a certain degree of randomness so long as it's only seeded once. But I won't use rand for any serious application, precisely due to the lack of guarantees.
It has not to be random but pseudo-random (reproducible and deterministic) as stated in POSIX:
The rand() function shall compute a sequence of pseudo-random integers
in the range [0, {RAND_MAX}]
This specification says that it is aligned with ISO-C standard.
Your proposition of implementation does not provide a pseudo-random sequence, obviously. A quick definition of pseudo-random generator could be: "a generator that provides uniform distribution", which yours are clearly not providing such. Your values are too trivially correlated to each others.

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