Ви також можете це зробити в сферичних координатах, і в цьому випадку відхилення немає. Спочатку ви генеруєте радіус і два кути навмання, потім використовуєте формулу переходу для відновлення , y і z ( x = r sin θ cos ϕ , , ).xyzx=rsinθcosϕz = r cos θy=rsinθsinϕz=rcosθ
Ви генеруєте одночасно між і . Радіус і нахил неоднакові. Імовірність того, що точка знаходиться всередині кулі радіуса дорівнює тому функція щільності ймовірності дорівнює . Ви можете легко перевірити, що кубічний корінь рівномірної змінної має точно такий же розподіл, тому таким чином можна генерувати . Ймовірність того, що точка лежить у сферичному конусі, визначеному нахилом є або якщо0 2 π r θ r r 3 r 3 r 2 r θ ( 1 - cos θ ) / 2 1 - ( 1 - cos ( - θ ) ) / 2 θ > π / 2 θ s i n ( θ ) / 2ϕ02πrθrr3r3r2rθ(1−cosθ)/21−(1−cos(−θ))/2θ>π/2 . Отже щільність - це . Ви можете перевірити, що мінус аркозіна рівномірної змінної має належну щільність.θsin(θ)/2
Або, простіше кажучи, ми зможемо симулювати косинус рівномірно і .- 1 1θ−11
У R це виглядатиме, як показано нижче.
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
Під час написання та редагування цієї відповіді я зрозумів, що рішення менш тривіальне, ніж я думав.
Я думаю, що найпростіший та обчислювально найефективніший метод - це слідувати методу @ whuber для генерації на одиничній сфері, як показано на цій посаді, та масштабування їх за допомогою .r(x,y,z)r
xyz <- matrix(rnorm(3*n), ncol=3)
lambda <- runif(n)^(1/3) / sqrt(rowSums(xyz^2))
xyz <- xyz*lambda