What is the basis of generating random numbers in C++?
Is there some logic or principle behind that?
Are the numbers generated completely random?
Suppose I am running this program:
#include <iostream.h>
#include <stdlib.h>
#include <time.h>
int main()
{
/*
Declare variable to hold seconds on clock.
*/
time_t seconds;
/*
Get value from system clock and
place in seconds variable.
*/
time(&seconds);
/*
Convert seconds to a unsigned
integer.
*/
srand((unsigned int) seconds);
/*
Output random values.
*/
cout<< rand() << endl;
cout<< rand() << endl;
cout<< rand() << endl;
return 0;
}
What it shows:
http://img14.imageshack.us/img14/1538/98271820.png
It showed 205 twice.
The question was basically answered in comments and another answer, but I'll gather it up in one place.
C++ rand() function produces not a truly random sequence of numbers, but a pseudo-random one. This means that it is basically a pre-defined sequence of numbers which are "random", but fixed somewhere (actually, it's more complex than that, but this is a simplification for better understanding). Think of it as a long list of integers.
Each call to rand() function pulls the current number and moves the pointer to "current "random" number" to the next one.
What srand() function does is basically setting the pointer to some location in the list. If you don't call the srand() function on each launch, or call it with fixed parameter (seed), you will have the same sequence of numbers on each program launch.
When you're setting your seed from the seconds, if you launch your program twice within that second, your seed will be the same - hence producing the same result.
Try the following code:
#include <windows.h>
// << other code >>
for (int i=0; i<50; i++) {
time(&seconds);
srand(seconds);
cout<< seconds<<" "<<rand()<<endl;
Sleep(100);
}
You will notice, that each "seconds" value correspond to some fixed "first" value for the rand() function.
Starting with the second question:
Are the numbers generated completely random?
No, that is very unlikely to ever happen in a computer. They are "pseudo-random" numbers, which is some sequence of numbers that vary in range over time in a random-like fashion. But if you start with the same "seed", you get the same sequence each time. This predictability is sometimes very useful, as it allows repeating the same experiment several times with the same outcome - altering the seed, will allow a similar run to have a different outcome.
The function srand sets the seed. Some systems do have a function called randomize, but it is not part of the standard as such. If it does exist it sets the seed to something unknown to the code - such as the current time in milliseconds.
Is there some logic or principle behind that?
Yes. There are several methods for generating pseudo-randum numbers. Simple ones can be written in one or two lines of C code using regular int or long types, and just consists of taking the "current value" + some constant, multiplied by some large number and modulo some other large number.
More complex ones involve dozens of more lines of rather complicated math with large numbers - for example Mersenne Twister is a recent work that is available as source code if you search a little bit.
Related
This question already has an answer here:
std::random_shuffle produce the same result even though srand(time(0)) called once
(1 answer)
Closed 7 years ago.
I am writing a program that uses random numbers extensively in different ways and I am getting the same random numbers each time. I know to put srand(time(NULL));at the beginning of the program to seed the random number generator and so I have that, but it isn't working. Perhaps it has something to do with XCode or the Mac or something else? I can't find a similar problem online that I has a solution I haven't already tried. Some ways I'm using the random numbers are:
for (int i=0; i<num; i++)
{
chrom_arr[i] = i;
}
random_shuffle(&chrom_arr[0], &chrom_arr[num-1]);
(to get an array with a series of random ints between 0 and num-1)
int crossover = rand() % num;
and other simple things like that. Even though I have srand(time(NULL)); at the beginning, it still doesn't work. I've also tried srand(time(0)); and also putting it in different parts of the program, but I have since learned that's not right.
Alex, can you please post a small but complete program that fails to generate different random numbers every time you run it? I'd be interested to see it...
Here's one that (of course) does yield different numbers every time it is run on my Mac:
#include <iostream>
#include <ctime>
#include <cstdlib>
int main()
{
srand(time(NULL));
for (int i = 0; i < 10; ++i)
std::cout << rand() % 10 << std::endl;
return 0;
}
What does it do if you compile and run it several times on your computer?
UPDATE:
I thought you meant srand() + rand() also produced identical numbers every time. That is not true. However, you are right about the behaviour of srand() + random_shuffle(): it may indeed produce the same numbers every time, depending on your compiler. It does on my compiler (clang on Mac) too.
This is explained here.
You should try somethig like this:
srand(static_cast<unsigned int>(time(0)));
std::shuffle(chrom_arr.begin(), chrom_arr.end(), default_random_engine(rand()));
This will work as long as chrom_arr is a std::vector. Once you are using C++, I presume this is what you are trying to do.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have the following piece of code:
unsigned int randomInt()
{
mt19937 mt_rand(time(0));
return mt_rand();
};
If I call this code, for example 4000 times in a for loop, I don't get random unsigned integers, instead I get for example 1000 times one value and the next 1000 times I get the next value.
What am I doing wrong?
This happens because you call f 4000 times in a loop, which probably takes less than a mili second, so at each call time(0) returns the same value, hence initializes the pseudo-random generator with the same seed. The correct way is to initialize the seed once and for all, preferably via a std::random_device, like so:
#include <random>
#include <iostream>
static std::random_device rd; // random device engine, usually based on /dev/random on UNIX-like systems
// initialize Mersennes' twister using rd to generate the seed
static std::mt19937 rng{rd()};
int dice()
{
static std::uniform_int_distribution<int> uid(1,6); // random dice
return uid(rng); // use rng as a generator
}
int main()
{
for(int i = 0; i < 10; ++i)
std::cout << dice() << " ";
}
A source of randomness is a resource that belongs to your entire program, not to a single function. You should pretty much never create a source of randomness inside a routine used to return a random value.
Good options include:
Pass a source of randomness into your function
Make your source of randomness a global variable
Make your source of randomness a static variable, so that initialization happens once.
One thing you might think to try that you should not do is to replace time(0) with a similar function that has a higher resolution; while you will get different results, this will still generate poor quality random numbers, and may even be much slower than generating random numbers properly. (I believe there are random number generators that can work properly with such usage, but those have to be designed for that purpose)
I have following code:
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
cout << rand()%30<< endl;
return 0;
}
I run this code and always get 11. Please explain why if you know. I use latest codeblocks and c++
The rand() function does not generate a truly random number; it actually returns the next pseudo-random value in a sequence of values ranging from 0 to RAND_MAX. You can change the starting point in that sequence using srand().
A common technique is to initialise srand() using the current time using the time() function, as shown below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
srand(time(NULL));
printf("%d", rand());
return 0;
}
This causes the program to start generating numbers from a different point in the sequence every time it is run, making it appear to be less predictable.
To initialize the random number generator, you need to call srand() with a seed.
You only need to initialize it once.
You will get the same sequence of numbers with the same seed, so normally, people use the current time as seed as that is pretty much guaranteed to change between program executions:
srand(time(0));
rand() is an older random number generator, inherited from C. C++ has better RNG's available. Just use the std::default_random_engine if you don't want to worry about details.
Also, %30 reduces random-ness. You probably want a std::uniform_int_distribution<int>(0,30) there.
In order to use the random number generator to get different number set in each time call it, you should definitely use with time.h.
Include time.h below the then use like this;
srand(time(NULL));
printf("%d", rand());
This question already has answers here:
function with rand initializes matrix always the same way
(2 answers)
Seeding a random number generator C++ [duplicate]
(4 answers)
Closed 8 years ago.
I'm making a small "dungeons and dragons" type of program to help demonstrate rand() command to me. It's working just fine, except it always picks 2. Never 1. Help?
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
cout << "welcome to T's version of dungeons and dragons! \n Scenario:";
int Scenario1 = rand() % 2 + 1;
if(Scenario1==1){
cout << "you come across a sleeping traveler, Do you ignore him, or steal his loot?";
}
else {
cout << "you find an old bandit hideout in a cave. Do you ignore, or enter?";
}
}
rand() will essentially generate the same series of numbers every time if you don't seed it.
The seed determines how the rand function generates numbers. For better 'randomness', call the following once at the beginning of the program, for example as the first statement inside main:
srand(time(NULL));
This seeds the random number generator with the value of the current UNIX timestamp, which should be unique enough to guarantee a better illusion of randomness.
More information on srand here:
http://www.cplusplus.com/reference/cstdlib/srand/
Edit
As others have mentioned, it's better to use the functionality found in the <random> header, as this is a more modern approach that avoids many of the pitfalls of the srand/rand paradigm.
rand() will always generate the number in same sequence.
To generate totally random number you can use srand(time(0)); time() is available in header file called #include <ctime>
Fore more detail please have a look :: https://www.youtube.com/watch?v=naXUIEAIt4U
I'm new to programming.
I want to know exactly what rand() does.
Searching only yields examples on its usage. But none explain each step of how the function generates a random number. They treat rand() as a blackbox.
I want to know what rand() is doing; each step.
Is there a resource that will allow me to see exactly what rand() does?
This is all open source stuff isn't it? I'll settle for the disassembly, if there's no source.
I know it returns a random number, but how does it generate that number? I want to see each step.
Thank you.
Here is the current glibc implementation:
/* Return a random integer between 0 and RAND_MAX. */
int
rand (void)
{
return (int) __random ();
}
That's not much help, but __random eventually calls __random_r:
/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
same in all the other cases due to all the global variables that have been
set up. The basic operation is to add the number at the rear pointer into
the one at the front pointer. Then both pointers are advanced to the next
location cyclically in the table. The value returned is the sum generated,
reduced to 31 bits by throwing away the "least random" low bit.
Note: The code takes advantage of the fact that both the front and
rear pointers can't wrap on the same call by not testing the rear
pointer if the front one has wrapped. Returns a 31-bit random number. */
int
__random_r (buf, result)
struct random_data *buf;
int32_t *result;
{
int32_t *state;
if (buf == NULL || result == NULL)
goto fail;
state = buf->state;
if (buf->rand_type == TYPE_0)
{
int32_t val = state[0];
val = ((state[0] * 1103515245) + 12345) & 0x7fffffff;
state[0] = val;
*result = val;
}
else
{
int32_t *fptr = buf->fptr;
int32_t *rptr = buf->rptr;
int32_t *end_ptr = buf->end_ptr;
int32_t val;
val = *fptr += *rptr;
/* Chucking least random bit. */
*result = (val >> 1) & 0x7fffffff;
++fptr;
if (fptr >= end_ptr)
{
fptr = state;
++rptr;
}
else
{
++rptr;
if (rptr >= end_ptr)
rptr = state;
}
buf->fptr = fptr;
buf->rptr = rptr;
}
return 0;
fail:
__set_errno (EINVAL);
return -1;
}
This was 10 seconds of googling:
gcc implementation of rand()
How is the rand()/srand() function implemented in C
implementation of rand()
...
http://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01206.html
http://www.gnu.org/software/libc/manual/html_node/Pseudo_002dRandom-Numbers.html
I was gonna list the actual search, but seeing this is clearly a dupe, I'll just vote as dupe
You can browse the source code for different implementations of the C standard.
The question has been answered before, you might find what you're looking for at What common algorithms are used for C's rand()?
That answer provides code for glibc's implementation of rand()
The simplest reasonably good pseudo-random number generators are Linear Congruential Generators (LCGs). These are iterations of a formula such as
X_{n+1} = (a * X_n + c) modulo m
The constants a, c, and m are chosen to given unpredictable sequences. X_0 is the random seed value. Many other algorithms exists, but this is probably enough to get you going.
Really good pseudo-random number generators are more complex, such as the Mersenne Twister.
I guess, THIS is what you are looking for. It contains the detailed explanation of random function, and simple C program to understand the algo.
Edit:
You should check THIS as well. A possible duplicate.
Well, I believe rand is from the C standard library, not the C++ standard library. There is no one implementation of either library, there are several.
You could go somewhere like this page to view the source code for glibc, the c library used on most Linux distributions. For glibc you'd find it in source files under stdlib such as rand.c and random.c.
A different implementation, such as uClibc might be easier to read. Try here under the libc/stdlib folder.
Correct me if I'm wrong, but although this answer points to part of the implementation, I found that there is more to rand() used in stdlib, which is from [glibc][2]. From the 2.32 version obtained from here, the stdlib folder contains a random.c file which explains that a simple linear congruential algorithm is used. The folder also has rand.c and rand_r.c which can show you more of the source code. stdlib.h contained in the same folder will show you the values used for macros like RAND_MAX.
/* An improved random number generation package. In addition to the
standard rand()/srand() like interface, this package also has a
special state info interface. The initstate() routine is called
with a seed, an array of bytes, and a count of how many bytes are
being passed in; this array is then initialized to contain
information for random number generation with that much state
information. Good sizes for the amount of state information are
32, 64, 128, and 256 bytes. The state can be switched by calling
the setstate() function with the same array as was initialized with
initstate(). By default, the package runs with 128 bytes of state
information and generates far better random numbers than a linear
congruential generator. If the amount of state information is less
than 32 bytes, a simple linear congruential R.N.G. is used.
Internally, the state information is treated as an array of longs;
the zeroth element of the array is the type of R.N.G. being used
(small integer); the remainder of the array is the state
information for the R.N.G. Thus, 32 bytes of state information
will give 7 longs worth of state information, which will allow a
degree seven polynomial. (Note: The zeroth word of state
information also has some other information stored in it; see setstate
for details). The random number generation technique is a linear
feedback shift register approach, employing trinomials (since there
are fewer terms to sum up that way). In this approach, the least
significant bit of all the numbers in the state table will act as a
linear feedback shift register, and will have period 2^deg - 1
(where deg is the degree of the polynomial being used, assuming
that the polynomial is irreducible and primitive). The higher order
bits will have longer periods, since their values are also
influenced by pseudo-random carries out of the lower bits. The
total period of the generator is approximately deg*(2deg - 1); thus
doubling the amount of state information has a vast influence on the
period of the generator. Note: The deg*(2deg - 1) is an
approximation only good for large deg, when the period of the shift
register is the dominant factor. With deg equal to seven, the
period is actually much longer than the 7*(2**7 - 1) predicted by
this formula. */