Sie können dies auch in sphärischen Koordinaten tun. In diesem Fall erfolgt keine Zurückweisung. Zuerst erzeugen Sie den Radius und die beiden Winkel zufällig, dann verwenden Sie die Übergangsformel, um , y und z wiederherzustellen ( x = r sin θ cos ϕ , y = r sin θ sin ϕ , z = r cos θ ).xyzx=rsinθcosϕy=rsinθsinϕz=rcosθ
You generate ϕ unifomly between 0 and 2π. The radius r and the inclination θ are not uniform though. The probability that a point is inside the ball of radius r is r3 so the probability density function of r is 3r2. You can easily check that the cubic root of a uniform variable has exactly the same distribution, so this is how you can generate r. The probability that a point lies within a spherical cone defined by inclination θ is (1−cosθ)/2 or 1−(1−cos(−θ))/2 if θ>π/2. So the density θ is sin(θ)/2. You can check that minus the arccosine of a uniform variable has the proper density.
Or more simply, we can simulate the cosine of θ uniformly beteen −1 and 1.
In R this would look as shown below.
n <- 10000 # For example n = 10,000.
phi <- runif(n, max=2*pi)
r <- runif(n)^(1/3)
cos_theta <- runif(n, min=-1, max=1)
x <- r * sqrt(1-cos_theta^2) * cos(phi)
y <- r * sqrt(1-cos_theta^2) * sin(phi)
z <- r * cos_theta
In the course of writing and editing this answer, I realized that the solution is less trivial than I thought.
I think that the easiest and computationally most efficient method is to follow @whuber's method to generate (x,y,z) on the unit sphere as shown on this post and scale them with r.
xyz <- matrix(rnorm(3*n), ncol=3)
lambda <- runif(n)^(1/3) / sqrt(rowSums(xyz^2))
xyz <- xyz*lambda