I'm trying to write a C++ function that will return Gaussian random values, given their means and variances.

There is a library function rand(), which returns random numbers between 0 and RAND_MAX. RAND_MAX does not have a fixed value, but it is guarantied that it will be at least $2^{15}-1$. Its PDF is uniform.

I'm using Central Limit Theorem to transform this rand()into a Gaussian variable. What I'm exactly doing is a to call rand() for a user specified times, then add up their return values, then shift its mean to the user specified mean.

Gaussian PDF
In the plotting above, I called my Gaussian random generator for $10^7$ times, and plotted frequencies of its return values. As you see, its variance is huge, since it is created by sum of a lot of other random values.

It successfully returns a Gaussian variable with a Gaussian PDF and with the specified mean value. However, the problem is its variance. I'm stuck at this point, because I don't know how to change its variance to the user specified value.

This is my code (incomplete for now; the parameter "Variance" is ignored):

template <class T>
T Random::GetGaussian(T Mean /*= 0*/, T Variance /*= 1*/)
    T MeanOfSum = NUM_GAUSSIAN_SUMS / static_cast<T>(2);
    T Rand = 0;
    for (uint64_t i=0; i<NUM_GAUSSIAN_SUMS; i++)
        Rand += static_cast<T>(rand()) / RAND_MAX;
    return Rand - (MeanOfSum - Mean);

Assume that NUM_GAUSSIAN_SUMS is 100, and RAND_MAX is 32767.

I want to change variance of the random variable according to the parameter of the function. My question is, how can I change variance of this random variable? How can I do it?

  • 3
    $\begingroup$ There are better and faster ways than the central limit theorem for generating Gaussian random variables. Search for Box-Muller method for one; a ziggurat method is said to be even better. $\endgroup$ – Dilip Sarwate Mar 22 '12 at 1:08
  • $\begingroup$ stackoverflow.com/questions/7034930/… $\endgroup$ – nibot Mar 22 '12 at 11:14
  • 3
    $\begingroup$ In olden days when execution time was an important consideration, people would sum $12$ $U(0,1)$ random variables (not $100$) and subtract $6$ to get a simple approximation to a standard $N(0,1)$ random variable, and then scale $Y = \sigma X+\mu$ to get a $N(\mu,\sigma^2)$ random variable. (For why this works, see @Hilmar's answer). For many applications this simple method worked very well, but the values were restricted to the range $(\mu-6\sigma, \mu+6\sigma)$ and this simple idea was dropped by the wayside when Six-Sigma became a buzzword. $\endgroup$ – Dilip Sarwate Mar 22 '12 at 17:04
  • $\begingroup$ @DilipSarwate perhaps you should post those alternatives as an answer with a justification for why we would prefer it $\endgroup$ – Ivo Flipse Mar 28 '12 at 9:30
  • $\begingroup$ @IvoFlipse The answer to the question asked "How do I fix the variance after I have fixed the mean?" is essentially what the accepted answer by Hilmar says, as modified by the comments: fix the variance by scaling and then re-fix the mean, or better yet, don't begin by fixing the mean first since you will have to re-fix it later; fix the variance first by scaling and then fix the mean. The OP does not indicate that he/she is at all interested in better methods and has not even upvoted nibot's link which even has the code for the Box-Muller method. So I will leave things as they are. $\endgroup$ – Dilip Sarwate Mar 28 '12 at 12:31

Your initial algorithm creates a random variable that's uniformly distributed between 0 and 1. The variance of that is 1/12. If you sum NUM_GAUSSIAN_SUMS instances of that the variance will be NUM_GAUSSIAN_SUMS/12. In order to get to a target variance, V, you need to multiply the summed random variable with sqrt(V*12/NUM_GAUSSIAN_SUMS).

As a side note, a template will work reasonable well for floats and doubles but there will be significant numerical problems with any fixed point type.

| improve this answer | |

how can I change variance of this random variable?

By multiplication, of course. The variance of $c X$, where $c$ is the multiplicative constant and $X$ is your random variable, is $c^2$ the variance of $X$.

| improve this answer | |
  • $\begingroup$ Unfortunately, the mean of $cX$ is $c$ times the mean of $X$, and so one of the parameters that the OP set before trying to fix the variance has to be reset to the desired value. $\endgroup$ – Dilip Sarwate Mar 22 '12 at 1:24
  • 1
    $\begingroup$ Center, rescale, then restore the mean. Scaling a centered random variable won't affect the (zero) mean. $\endgroup$ – Emre Mar 22 '12 at 1:29

There is yet another way!

Think of it, what if you wanted some other distribution as opposed to Gaussian? In that case you couldn't really use Central Limit theorem; how do you then solve it?

There is a way to convert uniform random variable into arbitrary PDF. This method is called Inverse Transform Method

If $U[0-1]$ is uniformly distributed over the interval (0, 1), then

$$ X = F_X^{-1} (U) $$

has c.d.f. $F_X (x)$.

Hence, all you need to do is, apply the inverse CDF function to the variable you have retrieved from the uniform rv's sample.

Also, unlike the earlier methods - this will not require any iteration and won't depend on how many iterations will be taken to make results closers to Gaussian.

Here is one of the references that gives a proof of this.

| improve this answer | |
  • 3
    $\begingroup$ >There is yet another way! True, but irrelevant to the question under consideration which is specifically about Gaussian random variables. Neither the Gaussian CDF nor its inverse can be expressed in elementary terms using a finite number of operations, and so the suggested method cannot be used. $\endgroup$ – Dilip Sarwate Mar 25 '12 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.