Uniform random number generated was repeated - c++

I was trying to generate 100 uniform random variable from 0.0 to 1.0.
I used the time based seed to generate it but the number generated seems repeated a few before changing to another one. Was there any better way to simualte without repeating?
Output was like:
0.33456, 0.33456, 0.33456, 0.11256, 0.11256, 0.11256, 0.94092, 0.94092, ...
Real UniformDistributionGenerator(double range_from, double range_to) {
Real uniform_r_v = 0.0;
unsigned seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::mt19937 generator(seed);
std::uniform_real_distribution<double> distribution(range_from, range_to);
uniform_r_v = distribution(generator);
return uniform_r_v;
}

The simplest solution: static std::mt19937 generator(seed);
Seeded once per program run, as it should be.

Related

When is it preferable to use rand() vs a generator + a distribution? (e.g. mt19937 + uniform_real_distribution)

After going through the rabbit hole that is learning about rand() and how it's not very good at generating uniform pseudorandom data based on what I've dug into based on this post:
Random float number generation. I am stuck trying to figure out which strategy would yield better balance of performance and accuracy when iterated a significant number of times, 128*10^6 for an example of my use case.
This link is what led me to make this post, otherwise I would have just used rand(): rand() considered harmful
Anyway, my main goal is to understand whether rand() is ever preferable to use over the generator + distribution method. There doesn't seem to be very good info even on cppreference.com or cplusplus.com for performance or time complexity for either of the two strategies.
For example, between the following two random number generation strategies is it always preferable to use the 2nd approach?
rand()
std::mt19937 and uniform_real_distribution
Here is an example of what my code would be doing:
int main(){
int numIterations = 128E6;
std::vector<float> randomData;
randomData.resize(numIterations);
for(int i = 0; i < numIterations; i++){
randomData[i] = float(rand())/float(RAND_MAX);
}
}
vs.
#include<random>
int main(){
std::mt19937 mt(1729);
std::uniform_real_distribution<float> dist(0.0, 1.0);
int numIterations = 128E6;
std::vector<float> randomData;
randomData.resize(numIterations);
for(int i = 0; i < numIterations; i++){
randomData[i] = dist(mt);
}
}

create random number from a poisson dist. using MersenneTwister

Hi I have a simulation I'm runnning in which I get random numbers from a uniform and normal distributions easily:
#include <iostream>
#include "MersenneTwister.h"
using namespace std;
int main()
{
MTRand mtrand1;
double r1,r2;
r1 = mtrand.rand(); // from a uninform dist.
r2 = mtrand1.randNorm(); //from a normal dist.
}
I would like to use this random number generator to obtain a random number from a poisson distribution with mean 'A'.
Any idea about how to implement this procedure using the MersseneTwister code?
the code can be found here:
https://gcc.gnu.org/bugzilla/attachment.cgi?id=11960. and it is widely used.
You can use the standard library
#include<random>
double mean = 3.1415926;
std::mt19937 mt{std::random_device{}()};
std::poisson_distribution<> pd{mean};
auto n = pd(mt); // get a number
Do note that seeding with std::random_device is unlikely to be satisfactory.

Adding Gaussian noise

I have a .arff file which contains a list of float numbers. I need to add to every number a gaussian noise, which in MATLAB would be:
m = m+k*randn(size(m)
where m is one of the numbers in the list and k is a standard deviation and has value 0.1. What is the C++ equivalent to randn()?
Could you please provide an example?
Use std::normal_distribution with an appropriate generator (std::default_random_engine will usually work). See http://en.cppreference.com/w/cpp/numeric/random for details on all of the random number generation facilities of the C++ standard library.
(live example)
#include <iostream>
#include <iterator>
#include <random>
int main() {
// Example data
std::vector<double> data = {1., 2., 3., 4., 5., 6.};
// Define random generator with Gaussian distribution
const double mean = 0.0;
const double stddev = 0.1;
std::default_random_engine generator;
std::normal_distribution<double> dist(mean, stddev);
// Add Gaussian noise
for (auto& x : data) {
x = x + dist(generator);
}
// Output the result, for demonstration purposes
std::copy(begin(data), end(data), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n";
return 0;
}
Output:
0.987803 1.89132 3.06843 3.89248 5.00333 6.07448
Further considerations
For decent statistical properties, you'll probably want to choose the std::mersenne_twister_engine generator (or, for convenience, the std::mt19937 predefined version), and seed it using std::random_device:
std::mt19937 generator(std::random_device{}());
[Note: Seeding from std::random_device is a good practice to get into; if you use the current time as a seed, you can end up with the same seed value across multiple generators (e.g. when initialising several generators in a very short period of time). std::random_device will obtain entropy from the system, if available.]
In order to avoid passing the generator to the distribution every time, you can do something like:
auto dist = std::bind(std::normal_distribution<double>{mean, stddev},
std::mt19937(std::random_device{}()));
which you can then use as follows:
double val = dist();
(Live example with these modifications)
The c++ standard now includes several distributions for random numbers.
You are looking for std::normal_distribution.
In the documentation you can also find a code sample
// construct a trivial random generator engine from a time-based seed:
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator (seed);
std::normal_distribution<double> distribution (0.0,1.0);
std::cout << "some Normal-distributed(0.0,1.0) results:" << std::endl;
for (int i=0; i<10; ++i)
std::cout << distribution(generator) << std::endl;
The parameters given to the constructor, std::normal_distribution, are first mean (0.0) and standard-deviation (1.0).

C++ with OpenMP thread safe random numbers

I am trying to draw some random points, and then calculate smth with them. I am using few threads, but my random is not so random as it supposed to be... I mean when I am using rand() I gets correct answer, but very slow(because of static rand), so I am using rand_r with seed, but the answer of my program is always wird.
double randomNumber(unsigned int seed, double a, double b) {
return a + ((float)rand_r(&seed))/(float)(RAND_MAX) * (b-a);
}
my program:
#pragma omp parallel
for(int i = 0; i < points; i++){
seedX = (i+1) * time(NULL);
seedY = (points - i) * time(NULL);
punkt.x = randomNumber(seedX, minX, maxX);
punkt.y = randomNumber(seedY, minY, maxY);
...
}
I found some solution in other topics(some mt19937 generators etc), but i cant compile anything.
I am using g++ -fopenmp for compiling.(g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2)
edit:
seed = rand();
#pragma omp parallel
for(int i = 0; i < points; i++){
punkt.x = randomNumber(seed, minX, maxX);
punkt.y = randomNumber(seed, minY, maxY);
...
}
Re-seeding your generators within each iteration of the for loop is going to ruin their statistical properties.
Also, it's likely that you'll introduce correlation between your x and y values if you extract them using two linear congruential generators.
Keep it simple; use one generator, and one seed.
Going forward, I'd recommend you use mt19937 as it will have better properties still. Linear congruential generators can fail a chi squared test for autocorrelation which is particularly important if you are using it for an x, y plot.
I believe that others are trying to say is, seed one in constructor with srand(some number), then do not seed anymore.
class someRandomNumber
{
}

std::default_random_engine generate values between 0.0 and 1.0

I want to be able to generate random values between 0.0 and 1.0
I've tried to use
std::default_random_engine generator;
std::uniform_real_distribution<float> distribution(0.0, 1.0);
float myrand = distribution(generator);
Generating random value in a loop gives me always these values:
0.000022
0.085032
0.601353
0.891611
0.967956
0.189690
0.514976
0.398008
0.262906
0.743512
0.089548
What can I do to really get random values?
Doesn't seem that random if I always get the same ones.
// 1-st variant: using time() function for seed random distribution
std::default_random_engine generator(time(0));
std::uniform_real_distribution<double> distribution(first, last);
return distribution(generator);
If open multiple programs, with the same random number generator they will all output the same results, because they have the same value of seed which is time.
This issue solved by using random device, in the below code:
// 2-nd variant:
std::uniform_real_distribution<double> distribution(first, last);
std::random_device rd;
std::default_random_engine generator(rd());
return distribution(generator);
If you are referring to the fact that you get the same results for each execution of the program, that's because you need to provide a seed based on some naturally random value (e.g. some number input by the user, or the number of milliseconds elapsed since the computer was turned on, or since January 1, 1970, etc.):
#include <random>
std::default_random_engine generator;
generator.seed( /* ... */ );
// ^^^^^^^^^
// Provide some naturally random value here
std::uniform_real_distribution<float> distribution(0.0, 1.0);
float myrand = distribution(generator);
I have found another good solution...
double Generate(const double from, const double to)
{
std::random_device rd;
return std::bind(
std::uniform_real_distribution<>{from, to},
std::default_random_engine{ rd() })();
}
Modifying the nice solution above into a class to avoid constant
instantiation of the distribution and generator.
#include <random>
using namespace std;
class RangeRandGenerator {
uniform_real_distribution<double> dist;
random_device rd;
default_random_engine gen;
public:
RangeRandGenerator( double from, double to ) :
dist(from, to), gen(rd()) {}
double get() {
return dist(gen);
}
};