The setRandom function in the Eigen matrix library fills a given matrix with random numbers in the range [-1,1]. How can I extend this to generate numbers within any given range? I require floating point numbers and I am okay with pseudo-randomness.
I have tried doing the following:
B = LO + A.cast<double>().array()/(static_cast <double>(RAND_MAX)/(HI-LO));
Here A is the matrix in question and [LO,HI] is the range I am looking to fill it in. The problem is that the value of RAND_MAX for me is 2147483647 and this is messing up the entire calculation.
Any help is much appreciated.
This might help:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
double HI = 12345.67; // set HI and LO according to your problem.
double LO = 879.01;
double range= HI-LO;
MatrixXd m = MatrixXd::Random(3,3); // 3x3 Matrix filled with random numbers between (-1,1)
m = (m + MatrixXd::Constant(3,3,1.))*range/2.; // add 1 to the matrix to have values between 0 and 2; multiply with range/2
m = (m + MatrixXd::Constant(3,3,LO)); //set LO as the lower bound (offset)
cout << "m =\n" << m << endl;
}
Output:
m =
10513.2 10034.5 4722.9
5401.26 11332.6 9688.04
9858.54 3144.26 4064.16
The resulting matrix will contain pseudo-random elements of the type double in the range between LO
and HI
.
Combine the c++11 random number generators with a nullary expression from Eigen:
std::random_device rd;
std::mt19937 gen(rd()); //here you could also set a seed
std::uniform_real_distribution<double> dis(LO, HI);
//generate a 3x3 matrix expression
Eigen::MatrixXd::NullaryExpr random_matrix(3,3,[&](){return dis(gen);});
//store the random_number in a matrix M
Eigen::MatrixXd M = random_matrix;
Note that you get a new random number each time you call random_matrix(0,0)
. That's ok for matrix operations which access the element once. If you need a random matrix that is used in more than one place, you can save it into an Eigen matrix M
as shown in the last line.
If you can use C++ 11/14 , the following works.
#include <random>
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0.0,1.0);
double number = distribution(generator)
This will generate random float values between the range L and R for distribution(L,R)
How about this way?
#include<iostream>
#include<random>
#include <Eigen/Dense>
int main(){
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dis(0, 1);
Eigen::MatrixXf m = Eigen::MatrixXf::Zero(10,10).unaryExpr([&](float dummy){return dis(gen);});
cout<<"Uniform random matrix:\n"<<m<<endl;
cout<<"Mean: "<<m.mean()<<endl;
return 0;
}
Here I replaced NullaryExpr which was used in @davidhigh with unaryExpr. Reason for this is that I got some weird errors when I tried @davidhigh answer.
Edit: based on @arprice
#if EIGEN_VERSION_AT_LEAST(3, 3, 0)
auto rand_fn = [&](){return uni(gen);};
#else
auto rand_fn = [&](float){return uni(gen);};
#endif Eigen::Vector3d::NullaryExpr(rand_fn);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With