Identical Random Numbers Generated in C++ - c++

I've been banging my head against this for half an hour now, and have NO idea what's wrong.
I'm trying to generate a list of 10 random numbers, 1-100. But when I run it they all come out the same number. It is very frustrating! I thought that it was because the number was still stored in the RAM, but after re-randomizing the random number and the variable three times, it still comes out with the same number. What am I doing wrong?
Code:
main() {
int i;
int randnum;
srand(time(NULL));
randnum = rand() % 2;
for (i = 0; i < 10; i++) {
srand(time(NULL));
randnum = rand() % 100 + 1;
srand(time(NULL));
rand();
list[i] = randnum;
srand(time(NULL));
randnum = rand() % 100 + 1;
srand(time(NULL));
rand();
}
srand(time(NULL));
randnum = rand() % 100 + 1;
}

Don't call srand() more than once. This code likely takes less than a second to execute, so every time you call srand(time(NULL)) when time is measured in seconds on your implementation, you just reset the pseudo random number generator to the same seed, so all your numbers come out the same.

Don't reinitialize the generator with srand(time(NULL)). Use it only once, at the beginning of your code.

What you're doing wrong is that you're resetting the random number generator's state.
The reason its not obvious is because you're using time. time returns time_t, which, according to the standard is "the implementation’s best approximation to the current calendar time". This generally represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC. Now, your code will likely execute within a millisecond, so all your time calls return the same value.
So your code is equivalent to:
int const somenum = time(NULL);
srand(somenum); //reset state using some seed.
//rand() will always produce the same value after an
// srand call of the same seed.
randnum = rand() % 100 + 1;
srand(somenum); //reset state using some seed.
randnum = rand() % 100 + 1;
srand(somenum); //reset state using some seed.
randnum = rand() % 100 + 1;
srand(somenum); //reset state using some seed.
randnum = rand() % 100 + 1;
To test this, wait for a keypress between each call to rand and you will see they are different.
The way to fix this is to only call srand(time(NULL)) once, at the start.
Now, in C++11, there is another way:
#include <iostream>
#include <random>
int main()
{
const int rand_max = 20;
std::default_random_engine rng(std::random_device{}());
std::uniform_int_distribution<> dist(0, rand_max);
std::cout<<"This will always be as random a number as your hardware can give you: "<<dist(rng)<<std::endl;
return 0;
}
std::random_device makes use of a built in hardware random number generator if available, so you don't have to worry about seeding with time. If you really do want a pseudo random number, then just use a different random number generator.
You can also control the random number distribution in C++11.

Related

Produce a random seed to give to srand() - Not time(NULL)

I am currently writing a level generation program for the game Sokoban. I use the rand() function quite a lot to generate each level, and I thought that a nice feature would be for the user to be able to control the seed used for the generation, meaning that two people could enter the same seed and the generator would generate the same levels.
I have been using
srand(std::time(NULL));
to produce the seed which works fine and my program will generate the same levels with the same seed no problem. However, as std::time(NULL) return the system time in Milliseconds, it doesn't give very interesting or diverse numbers, i.e it would produce 1476894985, and then the next seed might be 1476897904.
To give some more interesting seeds I tried creating a random seed between 0 and 9999999999 using the following code:
typedef unsigned long long ull;
SokoGenerator::ull SokoGenerator::randomNumber(ull min, ull max, int divisor){
ull number = rand() % (max - min + 1)+ min;
while(number % divisor != 0){
number = rand() % (max - min + 1) + min;
}
return number;
}
srand(std::time(0));
genSeed = randomNumber(0, 999999999); }
srand(genSeed);
//Generate Levels After this point
But this seems to produce similar results, except they are a lot smaller now, i.e 45789, 46389, 47958.
Is there a better way to generate a good random seed between 0 and 9999999999 to give to the srand() function?
I ended up using the C++11 Uniform Distribution Random Number Generator to give me a value between 0 and 4,294,967,295 like so:
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution;
generator.seed(chrono::steady_clock::now().time_since_epoch().count());
random = distribution(generator);

generate random number in a range c++ [duplicate]

This question already has answers here:
How does modulus and rand() work?
(4 answers)
Closed 8 years ago.
I'm using the ncurses library to build a game. I'm having trouble generating the correct random numbers. The while loop below needs to keep generating random numbers until they are between 1 and 45(this is my y-axis limits on the standard screen). I can't figure out what I'm doing wrong because the while loop condition looks fine to me. The problem is that while loop starts running infinitely. Im not doing anything but printing the generated numbers at the end as i just want to see that the correct numbers are generated. can anyone please help me with this problem? The following is my int main.
int main()
{
int r,c,x=0;
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
//mvprintw(22,45,"<");
getmaxyx(stdscr,r,c);
int n,n2 = 0;
while((n<1)||(n>45)){
srand (time(NULL));
n = rand();
srand (time(NULL));
n2 = rand();
}
mvprintw(4,10,"First Random Number: %d\n", n);
mvprintw(5,10,"Second Random number: %d\n", n2);
getch();
endwin();
return 0;
}
This is how you can do it in C++:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen( rd());
std::uniform_int_distribution<> dis( 1, 45);
for (int n=0; n<1000; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
Using rand() % x is a flawed design because of the bias introduced be dividing a range not evenly. You can read this to learn more about the bias introduced by rand() % x.
You want to call srand once at the start of things and then use modulus to bring rand results into your range, something like:
srand(time(NULL));
n = rand() % 45 + 1;
n2 = rand() % 45 + 1;
Just like #unholySheep commented, rand() returns a value between 0 and RAND_MAX, which it a huge value. Therefore, it is very unlikely you will get quickly a value between 1 and RAND_MAX.
Therefore, the solution is to do the reminder of the division by the number you want:
n = 1 + rand() % 45;
You do not even need a while.
You can get a random number between 1 and 45 inclusive with:
n = rand() % 45 + 1;
It won't be perfect in terms of distribution but it'll be close enough for anyone who's neither a statistician nor a cryptographer, in which case you probably would be using real random numbers.
You should also call srand() once, at the start of your program somewhere, rather than multiple times, especially if you're using the current time to seed it.
Doing it multiple times within the same second will give you a decidedly non-random sequence such as:
42, 42, 42, 42, 42, 42, 42, ...

C++ generation of random numbers [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to generate different random number in a loop in C++?
This is my code:
for(i=0;i<10;i++)
{
srand ( time(NULL) );
cout<<time(NULL);
max=100,min=0;
for(j=0;j<3;j++)
{
cout<<(( (rand() % (max - min + 1)) + min)%5);
}
}
Now i get the output:
1357207288 0 1 4
1357207289 0 1 4
1357207290 0 1 4
and so on. I want to get different random numbers each time. How can I achieve this.
The reason you get the same repeatedly is because you initialize it with the same seed each time. That is, since you are performing so few operations, not a single second has passed since the first iteration of the loop to the last one. Hence, time(nullptr) will return the same for each iteration.
To solve this, move srand ( time(NULL) ); outside of the loop, which will mean setting the random seed only once.
srand ( time(NULL) );
for(int i=0;i<10;i++)
{
cout<<time(NULL);
int max=100;
for(int j=0;j<3;j++)
{
cout<<(( (rand() % (max - min + 1)) + min)%5);
}
}
You must move srand() outside of your loop, otherwise you receive the same numbers.
srand ( time(NULL) );
for(i=0;i<10;i++)
{
cout<<time(NULL);
max=100,
for(j=0;j<3;j++)
{
cout<<(( (rand() % (max - min + 1)) + min)%5);
}
}
If you don't you will use the same seed since the time will not change in the nanoseconds your program takes to execute.
srand(time(NULL));
printf("%d", rand() % 10+1);
for(i=1; i<rand()% max_length; i++) {
printf("%ld", rand() % 10);
}
This will generate random numbers (also random length of them).
You get the same results even with srand() out of the loop because in C the generation algorithm used by rand is guaranteed to only be advanced by calls to this function. In C++, this constraint is relaxed, and a library implementation is allowed to advance the generator on other circumstances (such as calls to elements of <random>). Put a sleep inside the loop and see what happens.
Obviously in plain C this doesn't happen.
However, boost libraries offers you some good PRNG functionality. Use it instead of the broken srand(time(NULL));

How do I generate totally a random number at a time?

I want to create 3 random number at a time (simultaneously). However, they returned me the same numbers at a time even though they are actually random. Example:
------------------------
Variable: A B C
------------------------
Time 1 : 5 5 5
Time 2 : 3 3 3
Time 3 : 9 9 9
------------------------
They suppose to be different numbers at all. From the observation, I can see that my code can only pick a random number at a time (interval 1 second). Here is my generator code that I'm using:
unsigned int CMain::GenerateRandom(int min, int max)
{
srand((unsigned)time(0));
unsigned int random_integer;
int lowest = min, highest = max;
int range = (highest - lowest) + 1;
random_integer = lowest + int(range * rand() / (RAND_MAX + 1.0));
return random_integer;
}
How could I generate a totally random numbers at a time? Please help.
Thank you.
Your issue here is you're resetting the random seed every call using the current time which you shouldn't do.
Call srand() once before querying any random numbers - that's all and more than enough.
Right now you always reset your random seed to the exact same value (as you use current time). Random numbers in PCs aren't really random at all. The same seed will always result in the same set of random numbers generated later on. This is intentional and used in e.g. savegames for games to always have the same things happen without having to save every random number generated, etc.
Don't call srand() each time you generate a new random number. Call it once at the start of your program and then just call rand() each time you need a new random number.
FYI: Values returned from rand() are not "totally random". They are pseudo-random numbers generated by an algorithm. (This is not related to your question though.)
The problem is that you are calling srand() for every iteration. Srand() is setting a seed based on the current timestamp. Therefore you only need to call srand() once, and just call rand() to generate a new pseudo-random number. I say pseudo-random because computers cannot generate truly random numbers.
Sample code:
#include <iostream>
#include <cstdlib>
int main()
{
int i, r;
srand(time(0));
for(i = 0; r <= 20000; i++)
r = rand();
return 0;
}
time(0) changes slowly. If you query GenerateRandom quickly you can get the same number multiple times.
But in general, that isn't a right way to generate random numbers. You want to seed the random number generator only once, before any other function uses it. Treat rand as a global singleton object. If any of your functions modifies its seed by calling srand, then the change will affect all other calls to rand.

Generating a random integer from a range

I need a function which would generate a random integer in a given range (including boundary values). I don't have unreasonable quality/randomness requirements; I have four requirements:
I need it to be fast. My project needs to generate millions (or sometimes even tens of millions) of random numbers and my current generator function has proven to be a bottleneck.
I need it to be reasonably uniform (use of rand() is perfectly fine).
the minimum-maximum ranges can be anything from <0, 1> to <-32727, 32727>.
it has to be seedable.
I currently have the following C++ code:
output = min + (rand() * (int)(max - min) / RAND_MAX)
The problem is that it is not really uniform - max is returned only when rand() = RAND_MAX (for Visual C++ it is 1/32727). This is a major issue for small ranges like <-1, 1>, where the last value is almost never returned.
So I grabbed pen and paper and came up with following formula (which builds on the (int)(n + 0.5) integer rounding trick):
But it still doesn't give me a uniform distribution. Repeated runs with 10000 samples give me ratio of 37:50:13 for values values -1, 0. 1.
Is there a better formula? (Or even whole pseudo-random number generator function?)
The simplest (and hence best) C++ (using the 2011 standard) answer is:
#include <random>
std::random_device rd; // Only used once to initialise (seed) engine
std::mt19937 rng(rd()); // Random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // Guaranteed unbiased
auto random_integer = uni(rng);
There isn't any need to reinvent the wheel, worry about bias, or worry about using time as the random seed.
A fast, somewhat better than yours, but still not properly uniform distributed solution is
output = min + (rand() % static_cast<int>(max - min + 1))
Except when the size of the range is a power of 2, this method produces biased non-uniform distributed numbers regardless the quality of rand(). For a comprehensive test of the quality of this method, please read this.
If your compiler supports C++0x and using it is an option for you, then the new standard <random> header is likely to meet your needs. It has a high quality uniform_int_distribution which will accept minimum and maximum bounds (inclusive as you need), and you can choose among various random number generators to plug into that distribution.
Here is code that generates a million random ints uniformly distributed in [-57, 365]. I've used the new std <chrono> facilities to time it as you mentioned performance is a major concern for you.
#include <iostream>
#include <random>
#include <chrono>
int main()
{
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::duration<double> sec;
Clock::time_point t0 = Clock::now();
const int N = 10000000;
typedef std::minstd_rand G; // Select the engine
G g; // Construct the engine
typedef std::uniform_int_distribution<> D; // Select the distribution
D d(-57, 365); // Construct the distribution
int c = 0;
for (int i = 0; i < N; ++i)
c += d(g); // Generate a random number
Clock::time_point t1 = Clock::now();
std::cout << N/sec(t1-t0).count() << " random numbers per second.\n";
return c;
}
For me (2.8 GHz Intel Core i5) this prints out:
2.10268e+07 random numbers per second.
You can seed the generator by passing in an int to its constructor:
G g(seed);
If you later find that int doesn't cover the range you need for your distribution, this can be remedied by changing the uniform_int_distribution like so (e.g., to long long):
typedef std::uniform_int_distribution<long long> D;
If you later find that the minstd_rand isn't a high enough quality generator, that can also easily be swapped out. E.g.:
typedef std::mt19937 G; // Now using mersenne_twister_engine
Having separate control over the random number generator, and the random distribution can be quite liberating.
I've also computed (not shown) the first four "moments" of this distribution (using minstd_rand) and compared them to the theoretical values in an attempt to quantify the quality of the distribution:
min = -57
max = 365
mean = 154.131
x_mean = 154
var = 14931.9
x_var = 14910.7
skew = -0.00197375
x_skew = 0
kurtosis = -1.20129
x_kurtosis = -1.20001
(The x_ prefix refers to "expected".)
Let's split the problem into two parts:
Generate a random number n in the range 0 through (max-min).
Add min to that number
The first part is obviously the hardest. Let's assume that the return value of rand() is perfectly uniform. Using modulo will add bias
to the first (RAND_MAX + 1) % (max-min+1) numbers. So if we could magically change RAND_MAX to RAND_MAX - (RAND_MAX + 1) % (max-min+1), there would no longer be any bias.
It turns out that we can use this intuition if we are willing to allow pseudo-nondeterminism into the running time of our algorithm. Whenever rand() returns a number which is too large, we simply ask for another random number until we get one which is small enough.
The running time is now geometrically distributed, with expected value 1/p where p is the probability of getting a small enough number on the first try. Since RAND_MAX - (RAND_MAX + 1) % (max-min+1) is always less than (RAND_MAX + 1) / 2,
we know that p > 1/2, so the expected number of iterations will always be less than two
for any range. It should be possible to generate tens of millions of random numbers in less than a second on a standard CPU with this technique.
Although the above is technically correct, DSimon's answer is probably more useful in practice. You shouldn't implement this stuff yourself. I have seen a lot of implementations of rejection sampling and it is often very difficult to see if it's correct or not.
Use the Mersenne Twister. The Boost implementation is rather easy to use and is well tested in many real-world applications. I've used it myself in several academic projects, such as artificial intelligence and evolutionary algorithms.
Here's their example where they make a simple function to roll a six-sided die:
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
boost::mt19937 gen;
int roll_die() {
boost::uniform_int<> dist(1, 6);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
return die();
}
Oh, and here's some more pimping of this generator just in case you aren't convinced you should use it over the vastly inferior rand():
The Mersenne Twister is a "random
number" generator invented by Makoto
Matsumoto and Takuji Nishimura; their
website includes numerous
implementations of the algorithm.
Essentially, the Mersenne Twister is a
very large linear-feedback shift
register. The algorithm operates on a
19,937 bit seed, stored in an
624-element array of 32-bit unsigned
integers. The value 2^19937-1 is a
Mersenne prime; the technique for
manipulating the seed is based on an
older "twisting" algorithm -- hence
the name "Mersenne Twister".
An appealing aspect of the Mersenne
Twister is its use of binary
operations -- as opposed to
time-consuming multiplication -- for
generating numbers. The algorithm also
has a very long period, and good
granularity. It is both fast and
effective for non-cryptographic applications.
int RandU(int nMin, int nMax)
{
return nMin + (int)((double)rand() / (RAND_MAX+1) * (nMax-nMin+1));
}
This is a mapping of 32768 integers to (nMax-nMin+1) integers. The mapping will be quite good if (nMax-nMin+1) is small (as in your requirement). Note however that if (nMax-nMin+1) is large, the mapping won't work (For example - you can't map 32768 values to 30000 values with equal probability). If such ranges are needed - you should use a 32-bit or 64-bit random source, instead of the 15-bit rand(), or ignore rand() results which are out-of-range.
Assume min and max are integer values,
[ and ] means include this value,
( and ) means do not include this value,
using the above to get the right value using C++'s rand().
Reference:
For ()[] define, visit Interval (mathematics).
For the rand and srand function or RAND_MAX define,
visit std::rand.
[min, max]
int randNum = rand() % (max - min + 1) + min
(min, max]
int randNum = rand() % (max - min) + min + 1
[min, max)
int randNum = rand() % (max - min) + min
(min, max)
int randNum = rand() % (max - min - 1) + min + 1
Here is an unbiased version that generates numbers in [low, high]:
int r;
do {
r = rand();
} while (r < ((unsigned int)(RAND_MAX) + 1) % (high + 1 - low));
return r % (high + 1 - low) + low;
If your range is reasonably small, there is no reason to cache the right-hand side of the comparison in the do loop.
I recommend the Boost.Random library. It's super detailed and well-documented, lets you explicitly specify what distribution you want, and in non-cryptographic scenarios can actually outperform a typical C library rand implementation.
Notice that in most suggestions the initial random value that you have got from rand() function, which is typically from 0 to RAND_MAX, is simply wasted. You are creating only one random number out of it, while there is a sound procedure that can give you more.
Assume that you want [min,max] region of integer random numbers. We start from [0, max-min]
Take base b=max-min+1
Start from representing a number you got from rand() in base b.
That way you have got floor(log(b,RAND_MAX)) because each digit in base b, except possibly the last one, represents a random number in the range [0, max-min].
Of course the final shift to [min,max] is simple for each random number r+min.
int n = NUM_DIGIT-1;
while(n >= 0)
{
r[n] = res % b;
res -= r[n];
res /= b;
n--;
}
If NUM_DIGIT is the number of digit in base b that you can extract and that is
NUM_DIGIT = floor(log(b,RAND_MAX))
then the above is as a simple implementation of extracting NUM_DIGIT random numbers from 0 to b-1 out of one RAND_MAX random number providing b < RAND_MAX.
In answers to this question, rejection sampling was already addressed, but I wanted to suggest one optimization based on the fact that rand() % 2^something does not introduce any bias as already mentioned above.
The algorithm is really simple:
calculate the smallest power of 2 greater than the interval length
randomize one number in that "new" interval
return that number if it is less than the length of the original interval
reject otherwise
Here's my sample code:
int randInInterval(int min, int max) {
int intervalLen = max - min + 1;
//now calculate the smallest power of 2 that is >= than `intervalLen`
int ceilingPowerOf2 = pow(2, ceil(log2(intervalLen)));
int randomNumber = rand() % ceilingPowerOf2; //this is "as uniform as rand()"
if (randomNumber < intervalLen)
return min + randomNumber; //ok!
return randInInterval(min, max); //reject sample and try again
}
This works well especially for small intervals, because the power of 2 will be "nearer" to the real interval length, and so the number of misses will be smaller.
PS: Obviously avoiding the recursion would be more efficient (there isn't any need to calculate over and over the log ceiling...), but I thought it was more readable for this example.
The following is the idea presented by Walter. I wrote a self-contained C++ class that will generate a random integer in the closed interval [low, high]. It requires C++11.
#include <random>
// Returns random integer in closed range [low, high].
class UniformRandomInt {
std::random_device _rd{};
std::mt19937 _gen{_rd()};
std::uniform_int_distribution<int> _dist;
public:
UniformRandomInt() {
set(1, 10);
}
UniformRandomInt(int low, int high) {
set(low, high);
}
// Set the distribution parameters low and high.
void set(int low, int high) {
std::uniform_int_distribution<int>::param_type param(low, high);
_dist.param(param);
}
// Get random integer.
int get() {
return _dist(_gen);
}
};
Example usage:
UniformRandomInt ur;
ur.set(0, 9); // Get random int in closed range [0, 9].
int value = ur.get()
The formula for this is very simple, so try this expression,
int num = (int) rand() % (max - min) + min;
//Where rand() returns a random number between 0.0 and 1.0
The following expression should be unbiased if I am not mistaken:
std::floor( ( max - min + 1.0 ) * rand() ) + min;
I am assuming here that rand() gives you a random value in the range between 0.0 and 1.0 not including 1.0 and that max and min are integers with the condition that min < max.