I need to genetate three .txt files filled with random int, calling the generate function in sepatared threads.
The problem is that as a result I have the same values in every .txt files.
A function that gererates and writes values:
void generateMoves(int limit, std::string outputPath) {
//open fstream
std::ofstream fout;
fout.open(outputPath);
if (!fout.is_open()) {
std::cout << "Error reading " << outputPath << " file. Exiting..." << std::endl;
exit(1);
}
static thread_local std::mt19937 generator;
std::uniform_int_distribution<int> distribution(1, 3);
//generating & writing moves
for (int i = 0; i < limit; i++) {
int value;
value = distribution(generator);
fout << value << std::endl;
}
fout.close();
}
I call threads like this from main():
int limit = 1000;
std::thread player1(generateMoves, limit, "player1.txt");
std::thread player2(generateMoves, limit, "player2.txt");
std::thread player3(generateMoves, limit, "player3.txt");
player1.join();
player2.join();
player3.join();
So, how do I separate int generation correctly?
Edit: Following the comment below, I putted diffent seed into each thread and everything works fine now. The random generation looks like this now:
// put different *s* into each thread
srand(s);
//generating & writing
for (int i = 0; i < limit; i++) {
int value;
value = rand() % 3 + 1;
fout << value << std::endl;
}
As the comments state, all your generators have been created from the same default seed. It suffices to give each generator a different seed:
std::random_device rd1;
static thread_local std::mt19937 generator(rd1());
This uses the (very slow) std::random_device, but only to generate a unique seed for the mt generator.
Related
I basically need to make an array and put it in the private member section, and have it work the random number generator. Im not even sure if my teacher is asking for an array to hold the 1000 values, or if I need to make an array for each variable (zero, one, ....). The rubric states to use the private member array to hold the count of values returned from calls to the random generator.
3 hours of youtube videos.
class Gen
{
private:
int Numbergenerated;
public:
Gen();
void set_Numbergenerated(int);
int get_Numbergenerated();
void gener();
void display(int zero, int one, int two, int three, int four, int five, int six, int seven, int eight, int nine);
};
Gen::Gen()....
void Gen::set_Numbergenerated(int n)...
int Gen::get_Numbergenerated()...
void Gen::gener()
{
int result_of_gener;
result_of_gener = rand() % 10;
set_Numbergenerated(result_of_gener);
}
void display....
int main()
{
Gen g;
unsigned seed;
int zero = 0, one = 0, two = 0, three = 0, four = 0, five = 0, six = 0, seven = 0, eight = 0, nine = 0, count, num;
seed = time(0);
srand(seed);
cout << "Press Enter key to begin generating numbers" << endl;
cin.get();
for (count = 0; count <= 1000; count++)
{
g.gener();
num = g.get_Numbergenerated();
cout << "Generation " << "+" << count << ":\t" << "Number generated: " << num << endl;
switch (num)
{
case 0: zero++;
break;.....
g.display(zero, one, two, three,four,five, six, seven, eight, nine);
`````````````
*******spots with ...... placed to save space, probably unimportant parts.
Once you fill the array with 1000 elements, you can use the count function to determine the number of occurrences of a specific value in the array. Here is how.
So, assuming you are using C++ arrays, we can declare the array in the private section of your class:
// An array of ints, with 1000 elements.
std::array<int,1000> randomNumberArray;
We can assume your set_Numbergenerated function adds a new random number to the array, so, in main(), we can generate and insert 1000 random numbers:
/** Generate 1000 random numbers to fill the array. */
for (size_t i = 0; i < 1000; i++)
{
g.gener();
}
Since our array is a private member, and not directly accessible from main, we can add a public member function to Gen to access the array for us. We can also tell this method to count the number of occurrences of a specific value in the array (a great C++ algorithm):
// Return the number of occurrences of 'val' in the array.
int Gen::get_Occurrences(int val) {
return std::count(this->randomNumberArray.begin(), this->randomNumberArray.end(), val);
}
Finally, we can call this method for each number of interest (0 through 9), and give the result of each to the display method call in main:
g.display(g.get_Occurrences(0), g.get_Occurrences(1), g.get_Occurrences(2),
g.get_Occurrences(3), g.get_Occurrences(4), g.get_Occurrences(5),
g.get_Occurrences(6), g.get_Occurrences(7), g.get_Occurrences(8), g.get_Occurrences(9));
These and a few other minor edits produced the output:
Press Enter key to begin generating numbers
Occurrences of each number [0 - 9]: 95 87 106 112 107 96 109 104 100 84
The problem is a little ambiguous. I tried to keep as much of your code as I could, but I may have removed parts that were required to be in the assignment.
The numberGenerated is a confusing variable. It seems that the more important thing you are trying to track is the frequencies of each digit. To do this, I created a 10 element vector which is zeroed by the constructor.
Then, as each number is stored into the object, the corresponding bucket in the array is incremented.
Note that the constructor also calls the seed function for the random number generator.
#include <iostream>
#include <random>
#include <string>
#include <vector>
class Gen {
private:
int Numbergenerated;
unsigned seed;
std::vector<int> frequencies;
public:
Gen();
void set_Numbergenerated(int);
int get_Numbergenerated();
void generate_random_number();
void display();
};
Gen::Gen()
{
seed = time(0);
srand(seed);
for (int i = 0; i < 10; i++) {
frequencies
.push_back(0);// create and zero 10 buckets in our frequencies vector
}
}
void Gen::set_Numbergenerated(int n)
{
Numbergenerated = n;
frequencies[n] = frequencies[n] + 1;
}
int Gen::get_Numbergenerated()
{
return Numbergenerated;
}
void Gen::generate_random_number()
{
int result_of_generate;
result_of_generate = rand() % 10;
set_Numbergenerated(result_of_generate);
}
void Gen::display(){
int sum = 0;
for(int i = 0; i < 10; i++) {
std::cout << i << "'s: " << frequencies[i] << " ";
sum += frequencies[i];
}
std::cout << std::endl;
std::cout << "Total generated: " << sum << std::endl;
}
int main()
{
Gen g;
std::cout << "Press Enter key to begin generating numbers" << std::endl;
// std::cin.get();
for (int count = 0; count < 1000; count++) {
g.generate_random_number();
int num = g.get_Numbergenerated();
std::cout << "Generation " << "+" << count << ":\t" << "Number generated: "
<< num << std::endl;
}
g.display();
}
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.
I would like to maintain the random number generator state as a member variable, so every object generated from this class will have its one. It is necessary, that everytime an object is generated the seed gets changed too.
I did the following thing, namely changing the seed through the object's constructer. The seeding I did with time(NULL) but this is not accurate enough, since the the objects get created way faster than within a second, haha.
#include <iostream>
#include <cmath>
#include<random>
#include<chrono>
#include <ctime>
class Test{
public:
Test();
std::mt19937 rng;
double randomNumber(double min, double max);
};
Test::Test(){
rng.seed(time(NULL));
}
double Test::randomNumber(double min, double max){
std::uniform_real_distribution<double> uniformDistribution(min, max);
return uniformDistribution(rng);
}
int main(){
Test a;
Sleep(1000*1);
Test b;
for (int i = 0; i < 10; i++){
std::cout << "Random number a: " << a.randomNumber(0, 10) << "\tRandom number b: " << b.randomNumber(0, 10) << std::endl;
}
}
I am struggling with the method described in [Seeding rand() for a C++ class by bames53.
Including this piece
std::mt19937 eng{ std::chrono::high_resolution_clock::now().time_since_epoch().count() };
into the class declarations yields the following error:
Error: no instance of constructor "std::merseene_twister_engine<_Ty,_Wx, many more things> argument types are (std::chrono::system_clock::rep)
Now I do not exactly know where the error comes from and how to achieve my problem. Please keep in mind I am more or less an c++ newby.
Thank you!
Given your description you could initialize the RNG once then pass it as a reference to the Test class:
class Test{
public:
Test(std::mt19937& rng): m_rng(rng){
}
std::mt19937& m_rng;
double randomNumber(double min, double max){
std::uniform_real_distribution<double> uniformDistribution(min, max);
return uniformDistribution(m_rng);
}
};
std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
Test a(rng);
Because this particular RNG has a very long period you can instantiate it once then draw values from it across all your classes that need the random number generation.
Sample usage:
std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
Test a(rng);
Test b(rng);
for(int i=0; i<10; ++i){
std::cout<< "a: " << a.randomNumber(0.0,1.0) << "b: " << b.randomNumber(5.0,6.0) << std::endl;
}
Here's this code in action: http://ideone.com/Lzyp22
I have a program which use pthreads. In each thread a random number is generated using the rand() (stdlib.h) function. But it seems like every thread is generating the same random number. What is the reason for that??.. Am I doing something wrong??.. Thanks
rand() is pseudo-random and not guaranteed to be thread-safe, regardless, you need to seed rand():
std::srand(std::time(0)); // use current time as seed for random generator
See std::rand() at cppreference.com for more details.
A sample program may look like this:
#include <cstdlib>
#include <iostream>
#include <boost/thread.hpp>
boost::mutex output_mutex;
void print_n_randoms(unsigned thread_id, unsigned n)
{
while (n--)
{
boost::mutex::scoped_lock lock(output_mutex);
std::cout << "Thread " << thread_id << ": " << std::rand() << std::endl;
}
}
int main()
{
std::srand(std::time(0));
boost::thread_group threads;
for (unsigned thread_id = 1; thread_id <= 10; ++thread_id)
{
threads.create_thread(boost::bind(print_n_randoms, thread_id, 100));
}
threads.join_all();
}
Note how the pseudo-random number generator is seeded with the time only once (and not per thread).
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