如何在编程语言中生成一些长度固定为 r 的同分布伪随机向量?

How to generate some identically distributed pseudo-random vectors with a fixed length r in a programming language?

例如,对于维度d=2,这意味着我们可以生成一个随机角度0<=a<2*pi,然后我们就可以使用

(x_1,x_2)=(r*cos(a),r*sin(a)) 作为随机向量。

然而,对于维度 d>=3,我们不能只生成一个角度并用它来表示向量。那么我们如何生成这样一个向量(x_1,...,x_d),它在x_1^2+x_2^2+...+x_d^2=r^2上同分布?


我刚刚想出了一个新想法,我们可以生成一个向量 (x_1,...,x_d),使得所有 i-r<=x_i<r,如果 x_1^2+x_2^2+...+x_d^2<=r^2 和如果 x_1^2+x_2^2+...+x_d^2>r^2,请放弃它。

但是有个缺点就是如果d很大的话,x_1^2+x_2^2+...+x_d^2<=r^2变的概率会很小。有没有更好的解决方案?

生成独立且服从标准正态分布的随机变量(X_1, X_2, ... X_d),然后除以sqrt(X_1^2+...+X_d^2)/r.

独立正态分布的联合分布是旋转对称的不仅是正确的,它还表征了正态分布。

您可以使用 Box-Muller transform.

从均匀随机变量中高效地生成具有标准正态分布的独立变量对

我看到了两种解决方法。

最直接的方法是,在伪代码中:

1. build n-dimensional vector x[0] through x[n-1] with random components
2. find radius
3. go to step 1 if radius > r; otherwise, normalize to radius r

这是不确定的,因为无法知道在找到可接受的球体之前需要循环多少次。此外,发现坏点的概率随着维数的增加而上升。

要理解原因(感谢评论者!),请想象一个 1x1 的正方形。在里面加一个r=1的圆圈。用随机点填充正方形。圆心和圆之间的所有点投影到圆上时都是均匀分布的。圆圈和正方形边界之间的所有点都不是——因为有太多的点,比如 45º;并且 none 在,比方说,90º。

非直截了当的版本是二维方法的概括:

1. assume that we are on an n-sphere; generate angles phi[0], ...phi[n-2] 
   for a polar-coordinates point
2. convert to cartesian coordinates x[0] through x[n-1]

根据维基百科n-sphere页面,公式为

x[0]   = r*cos(phi[0]);
x[1]   = r*sin(phi[0])*cos(phi[1]);
x[2]   = r*sin(phi[0])*sin(phi[1]);
...
x[n-2] = r*sin(phi[0])*sin(phi[1])* /*...*/ sin(phi[n-3])*sin(phi[n-2])
x[n-1] = r*sin(phi[0])*cos(phi[1])* /*...*/ sin(phi[n-3])*cos(phi[n-2])

实际算法可以更有效地实现(sin(phi[0])正在计算很多,例如)

为了避免不确定性,我推荐第二种方法。

编辑

上面没有列出的推荐方法在 Douglas 的回答和许多参考站点中: