Solved – Transform standard normally distributed numbers into arbitrary normal distribution

normal distributionrandom-generation

I need a random number generator with a normal distribution, with parameterizable mean and standard deviation. I have only a uniformly distributed random number generator. By applying a Box-Muller transform to two uniformly distributed numbers in [0,1), I get a standard normal distribution. However, I've become confused about how to get an arbitrary, parameterized normal distribution by this procedure.

Since you can use a z-transform to change a non-standard normal distribution into a standard one, I thought that I could just use the inverse of a z-transform, and pass the result of the Box-Muller-transformed uniformly distributed numbers into $(x \times \sigma) + \mu$, where $\sigma$ is the desired standard deviation and $\mu$ is the desired mean. I've become convinced that this is a mistake. My simulation, using the transformed RNG didn't behave properly (I'm able to compare it with a well-tested normally distributed RNG), and a plot of the transformed distribution doesn't look at all correct.

I think that what I need to do is to do something with the mean and standard deviation inside the Box-Muller code, rather than just processing its return value in a simple way. However, I'm confused about how to do this.

In case it's helpful, here is my Box-Muller code. (It's in the NetLogo language, which may not be familiar, but I think this bit code will be intelligible to anyone with programming experience.)

to-report box-muller-random-normal [mn stddev]
  if-else box-muller-cache-exists = 0 [  ; using 1 for true and 0 for false means we don't have to initialize to false in setup; just use default zero init value
    ; cache is unfilled, so compute new pair of values
    let x1 random-float 1
    let x2 random-float 1
    let y1 sqrt (-2 * ln x1) * cos (2 * pi * x2)
    let y2 sqrt (-2 * ln x1) * sin (2 * pi * x2)
    set box-muller-cache y2
    set box-muller-cache-exists 1
    report y1
  ][
    set box-muller-cache-exists 0    ; so cache will be refilled next time
    report box-muller-cache
  ]
end

Where would I insert transformations involving the mean and standard deviation? (to-report is NetLogo's function-definition command. The code using ...cache... variables is designed to remember one of the values between invocations, generating new numbers only if there is no remembered value.)

Best Answer

If $X \sim N(0,1)$, then $Y = \sigma X + \mu \sim N(\mu,\sigma^2)$. So, leave the RNG and Box-Muller alone, and when you get the generated variate, just multiply by $\sigma$ and add $\mu$. You could stick these inside the Box-Muller code if you really want just simple code by modifying

let y1 sqrt (2 - ln x1) * cos (2 * pi * x2)

to

let y1 sigma * sqrt (-2 * ln x1) * cos (2 * pi * x2) + mu

and similarly for y2.