I generate a few thousand object in my program based on the C++ rand() function. Keeping them in the memory would be exhaustive. Is there a way to copy the CURRENT seed of rand() at any given time? This would give me the opportunity to store ONLY the current seeds and not full objects. (thus I could regenerate those objects, by regenerating the exact same sub-sequences of random numbers)
An exhaustive solution is storing the full sequence of random numbers given by rand() - doesn't worth it.
Another would be solution is to implement my own class for randomized numbers.
Google gave me no positive clues. There are hundreds of articles teaching the basics of rand and srand, and I couldn't find the specific ones.
Does anyone know other random number generators with implemented seed-stealer?
Thank you for your fast answers! There are more possible answers/solutions to this question, so I made a list of your answers here.
SOLUTIONS:
The short answer is: there is no standard way to get the seed
The closest possible workaround is to save the INITIAL seed in the beginning, and count how many times you call the rand() function. I marked this as solution because it works on the current std::rand() function of every compiler (and this was the main question about). I've benchmarked my 2.0 GHz CPU, and found that I can call&count rand() 1,000,000,000 times in 35 seconds. This might sound good, but I have 80,000 calls to generate one object. This restricts the number of generations to 50,000 because the size of unsigned long. Anyway, here is my code:
class rand2
{
unsigned long n;
public:
rand2 () : n(0) {}
unsigned long rnd()
{
n++;
return rand();
}
// get number of rand() calls inside this object
unsigned long getno ()
{
return n;
}
// fast forward to a saved position called rec
void fast_forward (unsigned long rec)
{
while (n < rec) rnd();
}
};
Another way is to implement your own Pseudo-random number generator, like the one Matteo Italia suggested. This is the fastest, and possibly the BEST solution. You're not restricted to 4,294,967,295 rand() calls, and don't need to use other libraries either. It's worth mentioning that different compilers have different generators. I've compared Matteo's LCG with rand() in Mingw/GCC 3.4.2 and G++ 4.3.2. All 3 of them were different (with seed = 0).
Use generators from C++11 or other libraries as Cubbi, Jerry Coffin and Mike Seymour suggested. This is the best idea, if you're already working with them.
Link for C++11 generators: http://en.cppreference.com/w/cpp/numeric/random
(there are some algorithm descriptions here too)
Does anyone know other random number generators with implemented seed-stealer
All standard C++11 random number generators (also available in TR1 and in Boost) offer this functionality. You can simply copy the generator objects or serialize/deserialize them.
There's no standard way to obtain the current seed (you can only set it via srand), but you can reimplement rand() (which is usually a linear congruential generator) by yourself in a few lines of code:
class LCG
{
private:
unsigned long next = 1;
public:
LCG(unsigned long seed) : next(seed) {}
const unsigned long rand_max = 32767
int rand()
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void reseed(unsigned long seed)
{
next = seed;
}
unsigned long getseed()
{
return next;
}
};
Use srand() to set the seed. save the value you used as the seed.
http://cplusplus.com/reference/clibrary/cstdlib/srand/
The random number generation classes in C++11 support operator<< to store their state (mostly the seed) and operator>> to read it back in. So, basically, before you create your objects, save the state, then when you need to re-generate same sequence, read the state back in, and off you go.
rand() does not offer any way to extract or duplicate the seed. The best you can do is store the initial value of the seed when you set it with srand(), and then reconstruct the whole sequence from that.
The Posix function rand_r() gives you control of the seed.
The C++11 library includes a random number library based on sequence-generating "engines"; these engines are copyable, and allow their state to be extracted and restored with << and >> operators, so that you can capture the state of a sequence at any time. Very similar libraries are available in TR1 and Boost, if you can't use C++11 yet.
Is there a way to copy the CURRENT seed of rand() at any given time?
What follows is an implementation-specific way to save and restore the pseudo-random number generator (PRNG) state that works with the C library on Ubuntu Linux (tested on 14.04 and 16.04).
#include <array>
#include <cstdlib>
#include <iostream>
using namespace std;
constexpr size_t StateSize = 128;
using RandState = array<char, StateSize>;
void save(RandState& state) {
RandState tmpState;
char* oldState = initstate(1, tmpState.data(), StateSize);
copy(oldState, oldState + StateSize, state.data());
setstate(oldState);
}
void restore(RandState& state) {
setstate(state.data());
}
int main() {
cout << "srand(1)\n";
srand(1);
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << "srand(1)\n";
srand(1);
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << "save()\n";
RandState state;
save(state);
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << "restore()\n";
restore(state);
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
cout << " rand(): " << rand() << '\n';
}
This relies on:
the same PRNG being used by the C library to expose both rand() and random() interfaces, and
some knowledge about the default initialization of this PRNG in the C library (128 bytes state).
If run, this should output:
srand(1)
rand(): 1804289383
rand(): 846930886
rand(): 1681692777
rand(): 1714636915
rand(): 1957747793
rand(): 424238335
rand(): 719885386
rand(): 1649760492
srand(1)
rand(): 1804289383
rand(): 846930886
rand(): 1681692777
rand(): 1714636915
save()
rand(): 1957747793
rand(): 424238335
rand(): 719885386
rand(): 1649760492
restore()
rand(): 1957747793
rand(): 424238335
rand(): 719885386
rand(): 1649760492
This solution can help in some cases (code that can't be changed, reproducing execution for debugging purpose, etc...), but it is obviously not recommended as a general one (e.g. use C++11 PRNG which properly support this).
You could try saving the value that you used to seed right before (or after) the srand.
So, for example:
int seed = time(NULL);
srand(time(NULL));
cout << seed << endl;
cout << time(NULL);
The two values should be the same.
I would recommend you to use the Mersenne Twister Pseudo-Random Number Generator. It is fast and offer very good random numbers. You can seed the generator in the constructor of the class very simply by
unsigned long rSeed = 10;
MTRand myRandGen(rSeed);
Then you just need to store somewhere the seeds you used to generate the sequences...
Related
I was trying to generate some random doubles in C++ (MSVC, though that isn't too important to me—I just didn't have another compiler to test) and I noticed that my quick program never generated negative numbers:
#include <iostream>
#include <random>
#include <ctime>
int main() {
std::mt19937 generator(clock());
std::uniform_real_distribution<double>
rand_dbl(std::numeric_limits<double>::min(),
std::numeric_limits<double>::max());
std::cout << "Double Limits: (" << std::numeric_limits<double>::min()
<< "," << std::numeric_limits<double>::max() << ")"
<< std::endl << std::endl;
int total_neg = 0;
for (int i=0; i<100; i++) {
double d = rand_dbl(generator);
if (d<0) total_neg++;
std::cout << d << " ";
}
std::cout << std::endl << std::endl
<< "Total negative random double is: " << total_neg << std::endl;
return 0;
}
No matter how many numbers I have it generate, it never generates a negative one. I understand why most of the numbers generated are in the 10307 - 10308 range (which isn't exactly what I wanted), but not why the numbers are always positive. I tried a few different generators (default, mt19937, minstd_rand0) without any difference in this aspect.
Can anyone describe why this is the case?
You set it up that way with the limits that you provided. std::numeric_limits<double>::min() gives the smallest positive double, and you used that as the lower bound on the distribution.
std::numeric_limits<double>::min()
Will return DBL_MIN which is the smalles value closest to 0 a double can hold. If you want the largest negative value then you need to use
std::numeric_limits<double>::lowest()
Which will return -DBL_MAX which is the largest negative value a double can hold.
From cppreference:
For floating-point types with denormalization, min returns the minimum positive normalized value.
(emphasis mine)
So it's pretty normal you only get positive values.
Could you tell what is displayed by those lines?
std::cout << "Double Limits: (" << std::numeric_limits<double>::min()
<< "," << std::numeric_limits<double>::max() << ")"
<< std::endl << std::endl;
I am making a small text-based game in c++ called "House Evolution" for fun. The game consists of 'searching under the couch cushions' to gain credits. When you search, the game is supposed to generate a random number anywhere from creditRate-5 to creditRate+5. How would I go about doing this using the rand() function, no matter what number creditRate is? Here is example code:
#include <iostream>
#include <unistd.h>
#include <string>
#include <cstdlib>
#include <math.h>
int main()
{
int creditRate = 30; // Just for example.
int credits;
int searching;
while (1) {
// Yes, I know, infinite loop...
std::cout << "Credits: " << credits << std::endl;
std::cout << "Type any key to search for credits: " << std::endl;
std::cout << "Searching...\n";
usleep(10000000); // Wait 10 seconds
searching = rand(?????????); // Searching should be creditRate-5 to creditRate+5
std::cout << "You found " << searching<< " credits\n";
credits += searching;
}
}
The way I would go about it is using rand % 11, to get a range of 11 numbers and then adding it to credit rate -5 to cover the range from creditrate-5 to creditrate+5.
So:
searching = rand() % 11 + creditRate - 5;
Try:
searching = rand() % 11 + creditRate-5; That's because your range is 11 (remember, there are 11 numbers from -5 to 5, for example) and the lower limit is creditRate-5.
Use the <random> header instead of rand(), because <random> provides facilities to generate these distributions correctly instead of making you do it yourself.
#include <iostream>
#include <thread>
#include <random>
int main()
{
int creditRate = 30; // Just for example.
// Searching should be creditRate-5 to creditRate+5
std::uniform_int_distribution<> random_credit_amount(creditRate - 5, creditRate + 5);
int credits = 0;
// arrange a source of randomness
std::random_device r;
std::seed_seq seed{r(),r(),r(),r(),r(),r()};
std::mt19937 pRNG(seed);
while (true) {
// Yes, I know, infinite loop...
std::cout << "Credits: " << credits << '\n';
std::cout << "Type any key to search for credits: " << '\n';
std::cout << "Searching...\n";
std::this_thread::sleep_for(std::chrono::seconds(10)); // Wait 10 seconds
int searching = random_credit_amount(pRNG);
std::cout << "You found " << searching<< " credits\n";
credits += searching;
}
}
<random> even provides more advanced options than the typical uniform distribution. For example, instead of having every values from creditRate - 5 to creditRate + 5 be equally likely, you could have values closer to creditRate be more likely than values further away, using a 'normal' (a.k.a. 'bell curve') distribution:
// credits found should be near creditRate
std::normal_distribution<> random_credit_amount(creditRate, 5);
and then in the loop:
int searching = std::round(random_credit_amount(eng));
(You don't have to change the code in the loop at all, but it skews the distribution a bit. Performing proper rounding avoids the skew.)
Notice another change I made, replacing the non-standard usleep with the standard this_thread::sleep_for. Notice that this code makes the comment entirely redundant:
std::this_thread::sleep_for(std::chrono::seconds(10)); // Wait 10 seconds
And one can just as easily ask for sleep durations of microseconds or hours
std::this_thread::sleep_for(std::chrono::hours(2));
std::this_thread::sleep_for(std::chrono::microseconds(50));
This question already has answers here:
How to generate different random numbers in a loop in C++?
(13 answers)
Closed 7 years ago.
I'm having trouble with a random generator.
I'm trying to print out random values and I'm getting almost the same value every single time.
This is what I have:
void Deck::shuffle() {
StackNode<Card>* top = stack->top;
for (int i = 0; i < stack->numNodes - 1; i++) {
int x = random(i);
StackNode<Card>* temp = findCard(x);
//cout << "Random index was: " << random(i) << endl;
//cout << "Face value of random was: " << temp->data.getFaceVal() << endl;
cout << "Top: " << top->data.getFaceVal() << endl;
cout << "Temp: " << temp->data.getFaceVal() << endl;
swapX(top,temp);
}
}
Here's my random generator function:
int random(int index) {
int r;
srand(time(NULL));
cout << "Index: " << index << endl;
r = rand() % 50;
cout << "Random value: " << r << endl;
return r;
}
I think you can use std::shuffle here for your problem. Like this:
#include <vector>
#include <algorithm>
void Deck::shuffle() {
StackNode<Card>* top = stack->top;
std::vector<StackNode<Card>*> cards;
for (int i = 0; i < stack->numNodes - 1; i++) {
cards.push_back(findCard(i))
}
std::shuffle(cards.begin(), cards.end());
for (auto card : cards) {
std::cout << card->data.getFaceVal() << std::endl;
}
}
By the way, I would recommend you to call srand only once in your code.
rand() is a pseudo random number generator. The numbers it generates appear to be random, but they are generated by a completely deterministic function. The seed that you give it with sand() determines the starting point for the function. If you give it the same seed it will generate the same sequence of random numbers. You can try this and see for your self by seeding with a literal, like srand(200) and running the program several times, you will get the exact same results.
If you want different results each time you have to seed with something that will be different each time the program runs, so time is often used as a seed. In your case you are in a very tight loop so many of the calls in a row use the same time value.
If you call srand() once, before your loop this problem will go away.
This question already has answers here:
Why does rand() yield the same sequence of numbers on every run?
(7 answers)
Closed 5 years ago.
I just finished coding a Minesweeper type game, and everything's good except for that each time I run the application, it generates the same number (I ran it 3 different times, saved the output to 3 text files and used the diff command in Linux, it didn't find any differences). It's seeded by time(NULL) so it should change every time, right?
Here's my code:
main.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Minesweeper/box.h"
#include <cstdio>
int main(int argc, char** argv){
using namespace std;
bool gameOver = false;
int x, y, score = 0;
const int HEIGHT = 10;
const int WIDTH = 10;
unsigned int Time = time(0);
cout << "Welcome to Minesweeper. " << endl;
//setup grid
Box grid[10][10];
for(int i = 0; i < WIDTH; i++)
for(int n = 0; n < HEIGHT; n++){
unsigned int value = rand() %100 + 1;
cout << value << endl;
if(value <= 38){
grid[i][n].setFill(MINE);
//cout << i << "," << n << " is mined." << endl;
}
else
grid[i][n].setFill(EMPTY);
}
for(int r = 0; r < WIDTH; r++)
for(int l = 0; l < HEIGHT; l++)
if(grid[r][l].getFill() == EMPTY)
cout << r << "," << l << " - EMPTY." << endl;
else if (grid[r][l].getFill() == MINE)
cout << r << "," << l << " - MINE." << endl;
while(!gameOver){
cout << "Enter coordinates (x,y): ";
scanf("%i,%i",&x,&y);
if(grid[x][y].getFill() == MINE)
gameOver = true;
else{
cout << "Good job! (You chose " << x << "," << y << ")" << endl;
score++;
}
}
cout << "You hit a mine! Game over!" << endl;
cout << "Final score: " << score << endl;
getchar();
return EXIT_SUCCESS;
}
It's seeded by time(NULL)
If it is, I can't see it. In fact, a search for it in your code returns nothing. The default behaviour, if you don't explicitly seed, is the same as if you had seeded it with the value 1.
You need to explicitly state something like:
srand (time (NULL));
at the start of main somewhere (and make sure you do this once and once only).
Though keep in mind this makes it dependent on the current time - if you start multiple jobs in the same second (or whatever your time resolution is), they'll start with the same seed.
From the C standard (on which C++ is based for these compatibility features):
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.
You need to seed randomizer. Call srand() at the beginning.
To add to the answers by others, you can use the Mersenne Twister Algorithm, which is a part of the C++11 library. Its fast becoming a standard in many common softwares to generate random numbers.
For example, this is the function I wrote, which I use often to generate random numbers in my other codes:
std::vector<double> mersennetwister(const int& My,const int& Mz,
const int& Ny,const int& Nz)
{
int ysize = (My + 2*Ny + 1);
int zsize = (Mz + 2*Nz + 1);
int matsize = ysize*zsize;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// Seeding the generator with the system time
std::mt19937_64 generator (seed);
// Calling the Mersenne-Twister Generator in C++11
std::uniform_real_distribution<double> distribution(0,1);
// Specifying the type of distribution you want
std::vector<double> randarray(matsize,0);
// Saving random numbers to an array
for (int i=0;i<matsize;++i)
{
randarray[i] = distribution(generator); // Generates random numbers fitting the
// Distribution specified earlier
}
return(randarray);
}
Bottomline: C++11 has some excellent features for numerical operations and it would be a good idea to look into them. As for the Mersenne Twister, http://en.wikipedia.org/wiki/Mersenne_twister
int main()
{
int numbers[30];
int i;
// making array of 30 random numbers under 100
for(i=0;i<30;i++)
{
numbers[i] = rand() % 100;
}
// finding the greatest number in the array
int greatest = 0;
srand(1);
for(i=0;i<30;i++)
{
if ( numbers[i] > greatest)
greatest = numbers[i];
}
How do I then tell the program to display the max value of the array??
Thank you
To display it in the basic console output:
#include <iostream>
...
std::cout << "Max value is: " << greatest << "\n";
#include <iostream>
std::cout << greatest << '\n';
On a sidenote, you might want to call srand() before your call rand() (and might want to supply a more meaningful parameter).
If you are not doing this for home work I would suggest using std::max_element (available in <algorithm>).
std::cout << "Max Value: " << *(std::max_element(number, numbers+30)) << std::endl;
Otherwise, in your program all thats left to do is to print the value. You could use std::cout (available in <iostream>). After you've computed the great in the for loop.
// Dump the value greatest to standard output
std::cout << "Max value: " << greatest << std::endl;
Is this what you're referring to?
printf("%d", greatest);
Make sure to include "cstdio".
std::cout << greatest <<endl;