I am trying to generate N(0,1) using uniform(0,1) for a simulation but can't get the code to run.
Firstly, my x is found by making X the subject for the CDF of normal followed by getting out the histogram. This is followed by imposing a normal curve to see if it fits. Below is my code.
sigma=1; mu=0
u<-runif(n)
x<-mu + sqrt(2*sigma(log(u*sigma*sqrt(2*pi))))
hist(x, Freq=F)
xpt<-seq(-5,5,0.1)
ypt<-dnorm(xpt,0,1)
lines(xpt,ypt,col=2)
You seem to invert PDF (probability density function) not CDF (cumulative density function).
Actually, Normal random variable is not generated with inverse CDF, as its CDF is not in closed form.
Check out Box-Muller transform. You simulate two independent sets of uniform random variables:
u <- runif(1000)
v <- runif(1000)
x <- sqrt(-2 * log(u)) * cos(2 * pi * v)
# y <- sqrt(-2 * log(u)) * sin(2 * pi * v)
Then x is from N(0, 1), and (x, y) are bivariate normal, with zero mean and identity covariance.
Source for all my comments:
Averill M. Law, W. David Kelton, Simulation Modeling and Analysis, third edition, McGraw-Hill, 2000. ISBN: 0-07-058290-4
The Box-Muller transform could be used by generating two U(0, 1) random variates.
`x1 = sqrt(-2 * log(u1)) * cos(2 * pi * u2)`
`x2 = sqrt(-2 * log(u1)) * sin(2 * pi * u2)`
To generalize:
box_muller <- function(n = 1, mean = 0, sd = 1)
{
x <- vector("numeric", n)
i <- 1
while(i <= n)
{
u1 <- runif(1, 0, 1)
u2 <- runif(1, 0, 1)
x[i] <- sqrt(-2 * log(u1)) * cos(2 * pi * u2)
if ((i + 1) <= n)
{
x[i + 1] <- sqrt(-2 * log(u1)) * sin(2 * pi * u2)
i <- i + 1
}
i <- i + 1
}
x * sd + mean
}
hist(box_muller(1000))
Note, however, that
While this method is valid in principle, i.e. if
U1andU2are truly IID U(0, 1) random variables, there is a serious difficulty ifU1andU2are actually adjacent random numbers produced by a linear congruential generator. (p. 465)
Marsaglia Bray Polar Method
This method is a two-step process where
- Generate
U1andU2as IID U(0, 1); letV[i] = 2 * U[i] - 1for i = 1, 2; and letW = V[1]^2 + V[2]^2.- If
W > 1, go back to step 1. Otherwise, letY = sqrt(-2 log(W)/W),X[1] = V[1] * Y, andX[2] = V2 * Y. ThenX[1]andX[2]are IID N(0, 1) random variates. (p. 466)
Implementation:
marsaglia_bray <- function(n = 1, mean = 0, sd = 1)
{
x <- vector("numeric", n)
i <- 1
while(i <= n)
{
u <- runif(2, 0, 1)
v <- 2 * u - 1
w <- sum(v^2)
if (w < 1)
{
y <- sqrt(-2 * log(w) / w)
z <- v * y
x[i] <- z[1]
if ((i + 1) <= n)
{
x[i + 1] <- z[2]
i <- i + 1
}
i <- i + 1
}
}
x * sd + mean
}
hist(marsaglia_bray(1000))
You may also consider the Ziggurat Alogrithm
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