【算法】如何在圆中随机均匀地取一点

849 阅读1分钟

要求: 在半径为1的圆内,实现在圆内随机均匀地取一点,返回点的[x,y]

1. 拒绝采样法(蒙特卡洛方法)

在圆的外切正方形内生成随机点,然后判断点是否在圆内,如果不在圆内就舍弃掉,直到生成在圆内的点就返回。

image.png

代码

function getPoint() {
  while (true) {
    // 生成[-1, 1]范围随机的x,y坐标
    const x = Math.random() * 2 - 1;
    const y = Math.random() * 2 - 1;
    if (x * x + y * y <=1) {
      return [x, y];
    }
  }
}

2. 极坐标加密度函数

极坐标的做法是随机产生半径 R 和角度 thetaθ, 其中随机变量 thetaθ 是符合均匀分布的,但是R不符合均匀分布,直观来看,在圆的面积中,同一半径的点出现在一个圆周上,因此半径 x 出现的概率应该是周长除以面积。据此可写出概率密度函数 f(x)如下,其中 r 为最大半径:

image.png

若已知随机变量的概率分布函数 F(x),y 是 [0,1] 区间的均匀分布随机数,则具有概率分布函数 F(x) 的随机数可以用下式得到:x=F^-1(y)。

简单来说,要得到随机分布可以按照以下步骤:

  1. 求出概率分布函数 F(x)
  2. 求概率分布函数的反函数 F^-1(x)
  3. 把 [0,1]区间内均匀分布的随机数代入 x = F^-1(y)

代码:

function getPoint2() {
  const theta = Math.random() * 2 * Math.PI;
  const r = Math.random();
  const x = Math.sin(theta) * Math.sqrt(r);
  const y = Math.cos(theta)* Math.sqrt(r);
  return [x, y];
}

参考链接:

  1. letcode: 478: 在圆内随机生成点
  2. 均匀的生成圆和三角形内的随机点