拒绝采样 + 连续概率分布:求解《478. 在圆内随机生成点》

2022-06-05 13:59:41
拒绝采样 + 连续概率分布,求解《478. 在圆内随机生成点》

Uniform 概率分布(连续均匀分布)概率密度函数 PDF + 累积分布函数 CDF 公式

连续概率分布

概率密度函数 PDF + 累积分布函数 CDF
观察:722路公交车每20钟一班,灵芝随意出发到公交站,灵芝需等候公交车的时间为X。X~UNIF(0,20) 来自:https://anifacc.github.io/math/probability/2017/07/19/probability-56w-pdf-cdf/

PHP 随机小数

例题

478. 在圆内随机生成点

给定圆的半径和圆心的位置,实现函数 randPoint ,在圆中产生均匀随机点。
实现 Solution 类:
Solution(double radius, double x_center, double y_center) 用圆的半径 radius 和圆心的位置 (x_center, y_center) 初始化对象
randPoint() 返回圆内的一个随机点。圆周上的一点被认为在圆内。答案作为数组返回 [x, y] 。
示例 1:
输入:
["Solution","randPoint","randPoint","randPoint"]
[[1.0, 0.0, 0.0], [], [], []]
输出: [null, [-0.02493, -0.38077], [0.82314, 0.38945], [0.36572, 0.17248]]
解释:
Solution solution = new Solution(1.0, 0.0, 0.0);
solution.randPoint ();//返回[-0.02493,-0.38077]
solution.randPoint ();//返回[0.82314,0.38945]
solution.randPoint ();//返回[0.36572,0.17248]

答案

本题不能随机角度[0, 2 * Math.PI]。角速度相同,距离圆点越远的地方,线速度越高,在相同空间内停留的时间越短

拒绝采样

圆形的正切正方形内选点,选择在圆形内的点

var Solution = function(radius, x_center, y_center) {
  this.r = radius
  this.x = x_center
  this.y = y_center
};
Solution.prototype.randPoint = function() {
  while (true) {
    const dx = this.r * 2 * Math.random() - this.r // [0, 2Π) -> [-Π, Π]
    const dy = this.r * 2 * Math.random() - this.r
    if (dx * dx + dy * dy <= this.r * this.r) return [this.x + dx, this.y + dy]
  }
};
class Solution {
  r: number
  x: number
  y: number
  constructor(radius: number, x_center: number, y_center: number) {
    this.r = radius
    this.x = x_center
    this.y = y_center
  }

  randPoint(): number[] {
    while (true) {
      const dx = 2 * this.r * Math.random() - this.r
      const dy = 2 * this.r * Math.random() - this.r
      if (dx * dx + dy * dy < this.r * this.r) return [this.x + dx, this.y + dy]
    }
  }
}
type Solution struct {
  r float64
  x float64
  y float64
}
func Constructor(radius float64, x_center float64, y_center float64) Solution {
  return Solution{radius, x_center, y_center}
}
func (this *Solution) RandPoint() []float64 {
  for true {
    dx, dy := 2 * this.r * rand.Float64() - this.r, 2 * this.r * rand.Float64() - this.r
    if dx * dx + dy * dy <= this.r * this.r {
      return []float64{this.x + dx, this.y + dy}
    }
  }
  return nil
}
class Solution {
  function __construct($radius, $x_center, $y_center) {
    $this->r = $radius;
    $this->x = $x_center;
    $this->y = $y_center;
  }
  function randPoint() {
    while (true) {
      $dx = $this->r * 2 * M_PI * lcg_value() - $this->r;
      $dy = $this->r * 2 * M_PI * lcg_value() - $this->r;
      if ($dx * $dx + $dy * $dy <= $this->r * $this->r) return [$this->x + $dx, $this->y + $dy];
    }
  }
}
class Solution {
  Random random;
  double r, x, y;
  public Solution(double radius, double x_center, double y_center) {
    random = new Random();
    r = radius;
    x = x_center;
    y = y_center;
  }
  public double[] randPoint() {
    while (true) {
      double dx = 2 * r * random.nextDouble() - r;
      double dy = 2 * r * random.nextDouble() - r;
      if (dx * dx + dy * dy <= r * r) return new double[]{x + dx, y + dy};
    }
  }
}
class Solution:
  def __init__(self, radius: float, x_center: float, y_center: float):
    self.r = radius
    self.x = x_center
    self.y = y_center
  def randPoint(self) -> List[float]:
    while True:
      dx, dy = 2 * self.r * random.random() - self.r, 2 * self.r * random.random() - self.r
      if dx * dx + dy * dy <= self.r * self.r: return [self.x + dx, self.y + dy]

连续概率分布

var Solution = function(radius, x_center, y_center) {
  this.r = radius
  this.x = x_center
  this.y = y_center
};
Solution.prototype.randPoint = function() {
  r = Math.sqrt(Math.random())
  angle =  Math.random() * Math.PI * 2
  return [this.x + r * this.r * Math.cos(angle), this.y + r * this.r * Math.sin(angle)]
};
class Solution {
  r: number
  x: number
  y: number
  constructor(radius: number, x_center: number, y_center: number) {
    this.r = radius
    this.x = x_center
    this.y = y_center
  }
  randPoint(): number[] {
    const r = Math.sqrt(Math.random())
    const angle = Math.random() * Math.PI * 2
    return [this.x + r * this.r * Math.cos(angle), this.y + r * this.r * Math.sin(angle)]
  }
}
type Solution struct {
  r float64
  x float64
  y float64
}
func Constructor(radius float64, x_center float64, y_center float64) Solution {
  return Solution{radius, x_center, y_center}
}
func (this *Solution) RandPoint() []float64 {
  r, angle := math.Sqrt(rand.Float64()), 2 * math.Pi * rand.Float64()
  return []float64{this.x + r * this.r * math.Cos(angle), this.y + r * this.r * math.Sin(angle)}
}
class Solution {
  function __construct($radius, $x_center, $y_center) {
    $this->r = $radius;
    $this->x = $x_center;
    $this->y = $y_center;
  }
  function randPoint() {
    $r = sqrt(lcg_value());
    $angle = 2 * M_PI * lcg_value();
    return [$this->x + $r * $this->r * cos($angle), $this->y + $r * $this->r * sin($angle)];
  }
}
class Solution {
  Random random;
  double r, x, y;
  public Solution(double radius, double x_center, double y_center) {
    random = new Random();
    r = radius;
    x = x_center;
    y = y_center;
  }
  public double[] randPoint() {
    double R = Math.sqrt(random.nextDouble());
    double angle = 2 * Math.PI * random.nextDouble();
    return new double[]{x + R * r * Math.cos(angle), y + R * r * Math.sin(angle)};
  }
}
class Solution:
  def __init__(self, radius: float, x_center: float, y_center: float):
    self.r = radius
    self.x = x_center
    self.y = y_center
  def randPoint(self) -> List[float]:
    r, angle = math.sqrt(random.random()), 2 * math.pi * random.random()
    return [self.x + r * self.r * math.cos(angle), self.y + r * self.r * math.sin(angle)]