Random number generator producing identical results - c++

I am having trouble using the random header to create a simple random number generator.
#include <iostream>
#include <random>
using namespace std;
int main()
{
random_device rd; //seed generator
mt19937_64 generator{rd()}; //generator initialized with seed from rd
uniform_int_distribution<> dist{1, 6};
for(int i = 0; i < 15; i++)
{
int random = dist(generator);
cout << random << endl;
}
}
This code produces identical results every time I run the program. What am I doing wrong? Also is there a way to modify this code such that it will generate a floating point number between 0 and 1? I don't think the uniform_int_distribution will let me and I can't figure out which distribution to use.
EDIT: Posted a possible solution to my problem below

Here is what I came up with eventually:
#include <iostream>
#include <ctime>
#include <random>
using namespace std;
int main()
{
srand(time(0));
default_random_engine rd(rand());
mt19937_64 generator{rd()}; //generator initialized with seed from rd
uniform_real_distribution<double> dist{0,1};
for(int i = 0; i < 15; i++)
{
double random = dist(generator);
cout << fixed << random << endl;
}
}
It turns out that you actually CAN combine srand(time(0)) with an engine from the random header file, and their powers combined seem to produce random-feeling numbers better than I have managed with either alone. Please feel free to point out any problems with this arrangement.

Related

srand() is not working when used with non-constant parameter

I've got a problem with srand(). It only works when I use a number as a parameter, for example srand(1234), but when I try to use it with 'n' or with time (as below), then randint() keeps returning the same value.
#include <iostream>
#include <experimental/random>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
srand(time(nullptr));
for (int i = 0; i < 4; ++i) {
int random = experimental::randint(0, 9);
cout << random;
}
}
Thanks for your time.
The C function srand is meant to be used in combination with the C function rand. These are separate functions from those in C++'s std::experimental header. The randint function from the latter is meant to be used with the reseed function from the same header:
#include <experimental/random>
#include <iostream>
int main() {
std::experimental::reseed();
for (int i = 4; i--; ) {
int random = std::experimental::randint(0, 9);
std::cout << random << '\n';
}
}
However, there is no need to use experimental features here. Since C++11, there is std::uniform_int_distribution:
#include <iostream>
#include <random>
int main() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distrib(0, 9); // Default type is 'int'
for (int i = 4; i--; ) {
int random = distrib(gen);
std::cout << random << '\n';
}
}
This method is more flexible than the one from the C standard library and should, generally, be preferred in C++.

All objects made through constructor have the same vectors

I'm new to C++ and I am trying to create a basic genetic algorithm. I created a Chromosome class and want to create a Society class that generates a vector of these Chromosomes with randomly generated "genes". Genes being the vector in the Chromosome that holds values of 0 or 1. I was testing out the Chromosome constructor, and all of the objects have the same gene vectors. How can I make the constructor generate random values? I have included code below. Any other coding practice or optimization tips would also be extremely appreciated.
Source.cpp
#include "Chromosome.h"
#include "Society.h"
using namespace std;
int main()
{
Chromosome demo = Chromosome::Chromosome();
Chromosome demo2 = Chromosome::Chromosome();
return 1;
}
Chromosome.h
#pragma once
#include <vector>
using namespace std;
class Chromosome
{
private:
int fitness;
vector<int> genes;
public:
Chromosome();
void generateGenes();
int calculateFitness(),
getFitness();
vector<int> getGenes();
void setGenes(vector<int> child);
};
Chromosome.cpp
#include "Chromosome.h"
#include <cstdlib>
#include <ctime>
#include <numeric>
using namespace std;
Chromosome::Chromosome()
{
generateGenes();
Chromosome::fitness = calculateFitness();
}
void Chromosome::generateGenes()
{
srand(time(NULL));
for (unsigned i = 0; i < 10; i++)
{
unsigned chance = rand() % 5;
Chromosome::genes.push_back((!chance)? 1 : 0);
}
}
int Chromosome::calculateFitness()
{
int sum = 0;
for (unsigned i = 0; i < Chromosome::genes.size(); i++)
{
sum += Chromosome::genes[i];
}
return sum;
}
int Chromosome::getFitness()
{
return Chromosome::fitness;
}
vector<int> Chromosome::getGenes()
{
return Chromosome::genes;
}
void Chromosome::setGenes(vector<int> child)
{
Chromosome::genes = child;
}
You seed the random number generator with the same value time(NULL).
Two calls after eachother will return the same time_t. You'll generate one set of random numbers first, then reset the random number generator and generate them again.
Only call srand() once during the whole program run.
Also, use <random> instead to get better/faster random number generators.
Instead of rand() % 5; using <random>:
#include <random>
// A function to return a random number generator.
inline std::mt19937& generator() {
// the generator will only be seeded once since it's static
static std::mt19937 gen(std::random_device{}());
return gen;
}
// A function to generate unsigned int:s in the range [min, max]
int my_rand(unsigned min, unsigned max) {
std::uniform_int_distribution<unsigned > dist(min, max);
return dist(generator());
}
Then call it:
unsigned chance = my_rand(0, 4);
Your problem is the use of rand & srand in a C++ program.
srand(time(NULL));
unsigned chance = rand() % 5;
in this implementation, rand might return multiple numbers that will give you the same final result. for example:
19, 24, 190214, 49789, 1645879, 15623454, 4, 156489719, 1645234, 152349, ...
There are different ways of generate random numbers in C++, this one isn't recommended due to bad results.
One (of many) good ways to generate random, using "pseudo-random" in C++:
void Chromosome::generateGenes()
{
// Initialize random
std::random_device rd; // Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> dis(0, 5);
for (unsigned i = 0; i < 10; i++)
{
// Use random: dis(gen);
unsigned chance = dis(gen);
Chromosome::genes.push_back((!chance)? 1 : 0);
}
}
Include:
#include <random>
Right note by #TedLyngmo: Every time that function will be called (in your case, in every object creation in the constructor call), this code will make you generate a new random seed (In 'Initialize random' section). In more progress cases, or as the program grows, it is highly recommended to extract this initialize to another function (and maybe to a new class object for modular programming reason). In this response I demonstrated the general syntax of using this type of random in your case.
Read about:
Pseudo-random number generation
Uniform Distribution
Thanks to #M.M: How to succinctly, portably, and thoroughly seed the mt19937 PRNG?

How to use random_engine and mt19937 in for loops

I'm creating a simple ASCII game that is supposed to place 3 snakes on the screen. I tried to use a for loop to print all 3 snakes:
#include <iostream>
#include <conio.h>
#include <string>
#include <cstdlib>
#include <random>
#include <ctime>
using namespace std;
int main() {
char _levelTwo[20][20];
int minSizeRand = 1;
int maxSizeRand = 19;
//Random Enemie 1 Placement Engine
static random_device xSeed;
static mt19937 randGen(xSeed());
uniform_int_distribution<int> enemieX(minSizeRand, maxSizeRand);
static random_device ySeed;
static mt19937 randGen1(ySeed());
uniform_int_distribution<int> enemieY(minSizeRand, maxSizeRand);
int snakeRows = enemieX(xSeed);
int snakeCols = enemieY(ySeed);
//Tries to Print 3 Snakes
for (int i = 0; i < 3; i++) {
cout << "Snake x: " << snakeRows << endl;
cout << "Snake y: " << snakeCols << endl;
_levelTwo[snakeRows][snakeCols] = 'S';
}
cin.get();
return 0;
}
When The code above is called, it only prints one snake. I've tried a non-static engine and it still gives the same output. Is this because the engine needs to be reseeded? I've also printed 2 snakes by creating 2 different engines, but that seems like it wastes a lot of space and if I wanted 10 snakes I would need 10 different engines. How do you get different outputs from the same random_engine and mt19937 when using a for loop?
#include <iostream>
#include <conio.h>
#include <string>
#include <cstdlib>
#include <random>
#include <ctime>
using namespace std;
int main() {
char _levelTwo[20][20];
int minSizeRand = 1;
int maxSizeRand = 19;
//Random Enemie 1 Placement Engine
static random_device xSeed;
static mt19937 randGen(xSeed());
uniform_int_distribution<int> enemieX(minSizeRand, maxSizeRand);
static random_device ySeed;
static mt19937 randGen1(ySeed());
uniform_int_distribution<int> enemieY(minSizeRand, maxSizeRand);
int snakeRows = enemieX(xSeed);
int snakeCols = enemieY(ySeed);
//Sets placement of snake 1
_levelTwo[snakeRows][snakeCols] = 'S';
//Random Enemie Placement Engine
random_device xSeed2;
mt19937 randGen2(xSeed2());
uniform_int_distribution<int> enemieX2(minSizeRand, maxSizeRand);
random_device ySeed2;
mt19937 randGen3(ySeed2());
uniform_int_distribution<int> enemieY2(minSizeRand, maxSizeRand);
int snakeRows2 = enemieX2(xSeed2);
int snakeCols2 = enemieY2(ySeed);
//Sets placement of snake 2
_levelTwo[snakeRows2][snakeCols2] = 'S';
}
I've read C++ generating random numbers in a loop using default_random_engine, but it doesn't answer my question completely.
First, you don't need more than one random number generator in this case (you almost never need). There is also no need for it to be static. In the question you linked he needed it to be static because the generator was inside a function that was being called multiple times. Everytime the function was called a generator was being instantiated with almost same seed making it generate almost same numbers.
Just do
random_device rd;
mt19937 rng(rd());
This defines a random number generator rng with a seed generated by std::random_device. You don't need more of them, because one generator can generate endless sequence of numbers.
Then there are distributions. They work by defining a range in which you want the numbers to be generated. They are lightweight, storing just a pair of numbers. In your case you need 2 of them. One for the distribution of x coordinates and one for y coordinates (If they don't differ you need only one, bacause they would be defining the same range).
uniform_int_distribution<int> xDist(minX, maxX);
uniform_int_distribution<int> yDist(minY, maxY);
You generate numbers by passing the generator through the distribution like you would with a function.
int x = xDist(rng); //generator outputs one integer and updates its state to be able to generate the next one.
int y = yDist(rng);
Now you want to generate more than one position.
Generating the coordinates stays the same, but you have to do it inside the loop. In your first code you generate one position and use it twice, resulting in placing two enemies in the same place. Just include the generation inside the loop.
for (int i = 0; i < 2; i++) {
}
int x = xDist(rng);
int y = yDist(rng);
//do something with x,y
}

Generating a random double between a range of values

Im currently having trouble generating random numbers between -32.768 and 32.768. It keeps giving me the same values but with a small change in the decimal field. ex : 27.xxx.
Heres my code, any help would be appreciated.
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand( time(NULL) );
double r = (68.556*rand()/RAND_MAX - 32.768);
cout << r << endl;
return 0;
}
I should mention if you're using a C++11 compiler, you can use something like this, which is actually easier to read and harder to mess up:
#include <random>
#include <iostream>
#include <ctime>
int main()
{
//Type of random number distribution
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
//Mersenne Twister: Good quality random number generator
std::mt19937 rng;
//Initialize with non-deterministic seeds
rng.seed(std::random_device{}());
// generate 10 random numbers.
for (int i=0; i<10; i++)
{
std::cout << dist(rng) << std::endl;
}
return 0;
}
As bames53 pointed out, the above code can be made even shorter if you make full use of c++11:
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>
int main()
{
std::mt19937 rng;
std::uniform_real_distribution<double> dist(-32.768, 32.768); //(min, max)
rng.seed(std::random_device{}()); //non-deterministic seed
std::generate_n(
std::ostream_iterator<double>(std::cout, "\n"),
10,
[&]{ return dist(rng);} );
return 0;
}
Also, If you are not using c++ 11 you can use the following function instead:
double randDouble(double precision, double lowerBound, double upperBound) {
double random;
random = static_cast<double>(((rand()%(static_cast<int>(std::pow(10,precision)*(upperBound - lowerBound) + 1))) + lowerBound*std::pow(10,precision)))/std::pow(10,precision);
return random;
}
So, I think this is a typical case of "using time(NULL) isn't a great way of seeding random numbers for runs that start close together". There isn't that many bits that change in time(NULL) from one call to the next, so random numbers are fairly similar. This is not a new phenomena - if you google "my random numbers aren't very random", you'll find LOTS of this.
There are a few different solutions - getting a microsecond or nanosecond time would be the simplest choice - in Linux gettimeofday will give you a microsecond time as part of the struct.
It seams to be plainly obvious but some of the examples say otherwise... but i thought when you divide 1 int with another you always get an int? and you need to type cast each int to double/float before you divide them.
ie: double r = (68.556* (double)rand()/(double)RAND_MAX - 32.768);
also if you call srand() every time you call rand() you reset the seed which results in similar values returned every time instead of ''random'' ones.
I've added a for loop to your program:
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main () {
srand(time (NULL));
for (int i = 0; i < 10; ++i) {
double r = ((68.556 * rand () / RAND_MAX) - 32.768);
cout << r << endl;
}
return 0;
}
Example output:
31.6779
-28.2096
31.5672
18.9916
-1.57149
-0.993889
-32.4737
24.6982
25.936
26.4152
It seems Okay to me. I've added the code on Ideone for you.
Here are four runs:
Run 1:
-29.0863
-22.3973
34.1034
-1.41155
-2.60232
-30.5257
31.9254
-17.0673
31.7522
28.227
Run 2:
-14.2872
-0.185124
-27.3674
8.12921
22.4611
-0.414546
-21.4944
-11.0871
4.87673
5.4545
Run 3:
-23.9083
-6.04738
-6.54314
30.1767
-16.2224
-19.4619
3.37444
9.28014
25.9318
-22.8807
Run 4:
25.1364
16.3011
0.596151
5.3953
-25.2851
10.7301
18.4541
-18.8511
-0.828694
22.8335
Perhaps you're not waiting at least a second between runs?

What's wrong with my random number generator?

I'm just diving into some C++ and I decided to make a random number generator (how random the number is, it really doesn't matter). Most of the code is copied off then net but my newbie eyes cannot see anything wrong with this, is there any way this can be tweaked to give a number other than "6" each time?
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int random_number(int min, int max)
{
srand((unsigned)time(0));
int random_num;
int range=(max-min)+1;
random_num = min+int(range*rand()/(RAND_MAX + 1.0));
return random_num;
}
int main()
{
for(int i =0;i < 100;i++)
{
cout << random_number(3,10) << endl;
}
}
Add srand before the loop
srand((unsigned)time(0));
for(int i =0;i < 100;i++)
{
std::cout << random_number(3,10) << endl;
}
Don't call srand() within random_number(). This will re-seed the random number generator every call. For 100 calls, you'll very likely get the same seed every call, and therefore the same number.
The problem is that you use srand everytime. CPU is so fast that it will execute all this code in a single second, so you get the same seed each time.
Move srand out of the loop, call it only once.