Random Numbers (between 0 and 1)
Random numbers are usually generated with the following code:
//include files
#include <stdlib.h>
#include <time.h>
//code for generate random numbers
srand(time(0));
double rnum = ((double)rand()/RAND_MAX);
However, in practice this usually doesn’t work quite well. Because first, due to the RAND_MAX
is expand to be INT_MAX
, which is 32768, the random number generated are too coarse-grained. We can only get numbers like $\frac{1}{32768}$, $\frac{2}{32768}$ and so forth. Second, because the srand()
function doesn’t actually generate random numbers that spans well uniformly between 0 and 1, instead, it often gives numbers that are highly dependent on time, which will make random numbers concentrate at a specific region between 0 and 1 given a specific time.
Instead, we can use the following code to generate random numbers in range $[0, 1)$:
#include <random>
#include <chrono>
double random_zero_to_one(){
std::mt19937_64 rng;
// initialize the random number generator with time-dependent seed
uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::seed_seq ss{uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed>>32)};
rng.seed(ss);
// initialize a uniform distribution between 0 and 1
std::uniform_real_distribution<double> unif(0, 1);
// ready to generate random numbers
const int nSimulations = 10;
double currentRandomNumber = unif(rng);
return currentRandomNumber;
}
If we want random numbers between $[1,2)$, we can simply change unif(0,1)
to unif(1,2)
.
Sample from a distribution with specified probabilities
Actually, it doesn’t need to be a distribution. It is the same problem if the user specified weights instead of a distribution in the given array. We can normalize the array to make it a distribution first. Then generate a random number in range $[0,1)$, say $r$. Then, for every value in the given distribution, say $D_i$, if $r < D_i$, then return $i$ as the chosen index. Otherwise update $r$ by subtracting $D_i$: Then continue to next index until $r < D_i$ is satisfied.
The code are shown bellow:
int random_sample(double distribution[],int size){
//check if the array adds up to 1
double sum = 0.0;
REP (i, 0, size-1){
sum += distribution[i];
}
if(sum == 1.0){//valid
// will generate [0,1)
double rnum = random_zero_to_one();
REP(i, 0, size-1){
if (rnum < distribution[i]) return i;
else{
rnum -= distribution[i];
}
}
}else{//didn't get a valid distribution
//return -1 indicate that input not valid
return(-1);
}
}
Leave a Comment