Math 如何在正方形内生成一个随机点,而不是在正方形内切掉的圆内生成一个随机点

Math 如何在正方形内生成一个随机点,而不是在正方形内切掉的圆内生成一个随机点,math,random,Math,Random,参考图像: 红色圆圈的半径为r 蓝色正方形的边长为s 目标是在蓝色区域中生成一个随机点,但不在红色区域中生成 我已经有了一个解决方案,但它需要反复试验,这不是我喜欢的方法,这个问题有什么数学解决方案吗 这是我的方法 设rx和ry为随机变量 rx=0和s之间的随机数 ry=0和s之间的随机数 而(距离(rx,ry,0,0) y= s/2 。在3中用顶面截取的行,则在位置 S/2=席谭(W)< /代码>。< /LI> 笛卡尔点(xi,s/2)定义了rho的最大值:R=sqrt(xi^2+(s/2

参考图像:

红色圆圈的半径为r

蓝色正方形的边长为s

目标是在蓝色区域中生成一个随机点,但不在红色区域中生成 我已经有了一个解决方案,但它需要反复试验,这不是我喜欢的方法,这个问题有什么数学解决方案吗

这是我的方法

设rx和ry为随机变量

rx=0和s之间的随机数
ry=0和s之间的随机数
而(距离(rx,ry,0,0)返回rx ry不过,正如@Marc所说,从技术上讲,这是数学,而不是编程。但是,答案是生成一个随机点,然后确定从正方形中心到该点绘制的直线长度是否小于或等于圆的半径。如果是这样,请拒绝它并生成另一个。

您可以在[0..1]范围内生成两个数字,然后定义一个函数,将某个y的x映射到圆外的点

我建议您继续使用您现在的想法,它被正式称为,是一种仅使用统一随机数生成器从任意概率分布进行采样的相对常见的技术

随着维度数量的增加,减速的问题是不可避免的——这通常被称为

虽然有些人建议将圆中的点“推”到可接受/蓝色区域中的点,但如果不牺牲完全一致的概率分布,则很难做到这一点。(例如,我可以将圆中的所有点推到圆边界上最近的点,但这会使分布不均匀,因为圆边界的采样频率会更高。)



为了使您的代码尽可能高效,您应该在计算
(距离(rx,ry,0,0)
时尽可能不调用任何函数,并且使用像
+
*
这样的主位运算符,而不是像
exp(x,2)这样的库函数
。换句话说,直接在
if
语句中使用
x*x+y*y
(使用
r2=r*r;
).

我可以看到两种可能性。如果圆比正方形小得多,则在正方形内生成一个点,并检查它是在圆内还是在圆外。如果圆是正方形的很大一部分,则找到离圆心最远的正方形角的最大可能半径。生成一个半径在给定圆外,但不大于到最远角的距离的us。也生成θ。如果结果(r,θ)点在正方形内,然后接受它。构造方法确保它在圆外。

我不会进入数学与编程的讨论。对我来说,这两个问题都有。这是我的观点

您可以尝试将在[0,1]间隔内生成的点映射到蓝色区域。如果两种形状都是同心圆,则应给出正态分布。当您有一个正方形时,越靠近对角线,点越稀疏

其思想是在极坐标系下工作:

  • 假设图片的中心位于笛卡尔坐标
    (x,y)
    位置
    (0,0)
  • [0,1]
    间隔内生成一个数字
    a
  • 将此数字转换为角度
    w=2*pi*a
    。这将是你的极角。等式
    y=x*tan(w)
    定义了一条穿过图片中心的直线
  • 现在棘手的部分是:计算数字的径向部分(rho)的可接受极限。它必须大于圆的半径
    r
    ,并且小于步骤3中定义的直线截取正方形的点
  • 有四种可能性,正方形的每侧各有一种。“顶部”侧用于
    w
    的值从
    pi/4
    3pi/4
    的情况;“左侧”用于
    w
    的范围从
    3pi/4
    5pi/4
    的情况;“底部”在
    5pi/4
    7pi/4
    之间具有
    w
    ;并且“右侧”具有
    w
    7pi/4
    2pi
    以及从
    0
    pi/4
  • 以顶部行为例:它位于位置>代码> y= s/2 。在3中用顶面截取的行,则在位置<代码> S/2=席谭(W)< /代码>。< /LI>
  • 笛卡尔点
    (xi,s/2)
    定义了rho的最大值:
    R=sqrt(xi^2+(s/2)^2)
  • 现在在
    [0,1]
    间隔中生成另一个值
    b
  • 将此值映射到[r,r]间隔:
    rho=r+b*r
  • 最后得到你的数字
    X=rho*cos(w)
    Y=rho*sin(w)
    ,它们应该在蓝色区域
  • 请注意,从第5步开始,您必须检查正方形的哪一侧是您应该考虑的一侧(哪个值为
    w


    如上所述,问题在于对角线比沿主轴的方向长,从而产生更稀疏的分布。这取决于您是否存在问题。请注意,映射不会堆积靠近圆边缘的点。还要问问自己,方向检查是否可行(我假设正方形和圆形是您真正想要的粗糙近似值)。

    好的,如果rx和ry不是一个,为什么要拒绝它们呢?我们可以选择[-s,s]中的任何rx。因此

    rx = -s + 2*s*rand();
    
    if(rx<-R || rx>R) % if rx is outside the critical area, you are free on ry
        ry = -s + 2*s*rand();
    else % if rx is critical, we are restricted about choosing ry not within [-sqrt(R^2-rx^2),sqrt(R^2-rx^2)]
    {
        rand_inst = rand();
        if(rand_inst<0.5) % for the first possible interval [-s, -sqrt(R^2-rx^2)]
            ry = -s + 2*(s-sqrt(R^2-rx^2))*rand_inst;
        else % for the second possible interval [sqrt(R^2-rx^2), s]
            ry = (sqrt(R^2-rx^2) - (s-sqrt(R^2-rx^2)) ) + 2*(s-sqrt(R^2-rx^2))*rand_inst;
    }
    
    rx=-s+2*s*rand();
    如果(rxR)%rx在关键区域之外,则您可以在ry上自由活动
    ry=-s+2*s*rand();
    其他%