[ Team LiB ] Previous Section Next Section

11.13 Getting Floating-Point Values with Nonuniform Distributions

11.13.1 Problem

You want to select random real numbers in a nonuniform distribution.

11.13.2 Solution

The exact solution varies depending on the distribution. We provide implementations for many common distributions in this recipe.

11.13.3 Discussion

Do not worry if you do not know what a particular distribution is; if you have never seen it before, you really should not need to know what it is. A uniform distribution (as discussed in Recipe 11.12) is far more useful in most cases.

In all cases, we start with a number with uniform distribution using the API from Recipe 11.12.

Note that these functions use math operations defined in the standard math library. On many platforms, you will have to link against the appropriate library (usually by adding -lm to your link line).

#include <math.h>
   
#define NVCONST 1.7155277699141
   
double spc_rand_normalvariate(double mu, double sigma) {
  double myr1, myr2, t1, t2;
   
  do {
    myr1 = spc_rand_real(  );
    myr2 = spc_rand_real(  );
    t1 = NVCONST * (myr1 - 0.5) / myr2;
    t2 = t1 * t1 / 4.0;
  } while (t2 > -log(myr2));
  return mu + t1 * sigma;
}
   
double spc_rand_lognormalvariate(double mu, double sigma) {
  return exp(spc_rand_normalvariate(mu, sigma));
}
   
double spc_rand_paretovariate(double alpha) {
  return 1.0 / pow(spc_rand_real(  ), 1.0 / alpha);
}
   
double spc_rand_weibullvariate(double alpha, double beta) {
  return alpha * pow(-log(spc_rand_real(  )), 1.0 / beta);
}
   
double spc_rand_expovariate(double lambda) {
  double myr = spc_rand_real(  );
   
  while (myr <= 1e-7)
    myr = spc_rand_real(  );
  return -log(myr) / lambda;
}
   
double spc_rand_betavariate(double alpha, double beta) {
  double myr1, myr2;
   
  myr1 = spc_rand_expovariate(alpha);
  myr2 = spc_rand_expovariate(1.0 / beta);
  return myr2 / (myr1 + myr2);
}
   
#define SPC_PI 3.1415926535
   
double spc_rand_cunifvariate(double mean, double arc) {
  return (mean + arc * (spc_rand_real(  ) - 0.5)) / SPC_PI;
}

11.13.4 See Also

Recipe 11.12

    [ Team LiB ] Previous Section Next Section