如何在圆形分布中生成随机点

15

我想知道如何生成呈圆形分布的随机数。

我能够生成在矩形分布内的随机点,这些点生成在 (0 <= x < 1000, 0 <= y < 1000) 的正方形内:

那么,我该如何生成在圆形分布内的点,使得:

(x−500)^2 + (y−500)^2 < 250000?


2
然而,必须小心计算的方式。如果意图是在圆内具有均匀分布的随机(x,y)值,则许多可能的计算方式都无法实现该结果。 - Simon
1
http://mathworld.wolfram.com/DiskPointPicking.html - Veedrac
2
阅读此链接:http://stats.stackexchange.com/questions/120527/how-to-generate-random-points-uniformly-distributed-in-a-circle。 - vsoftco
可能是[在圆内生成随机点(均匀分布)]的重复问题(https://dev59.com/wG025IYBdhLWcg3wtobX)。 - aioobe
7个回答

15
import random
import math

# radius of the circle
circle_r = 10
# center of the circle (x, y)
circle_x = 5
circle_y = 7

# random angle
alpha = 2 * math.pi * random.random()
# random radius
r = circle_r * math.sqrt(random.random())
# calculating coordinates
x = r * math.cos(alpha) + circle_x
y = r * math.sin(alpha) + circle_y

print("Random point", (x, y))

在你的例子中,circle_x 为500,如同 circle_y 的取值也是500。而 circle_r 则为500。

另一种计算半径以获得均匀分布点的方法是基于这个答案的。

u = random.random() + random.random()
r = circle_r * (2 - u if u > 1 else u)

9
不确定原帖作者是否需要,但这个分布不会是均匀分布。 - andars
2
这种方法产生的(x,y)值分布不均匀 - 它们在圆的中心比边缘更加集中。如果这是期望的结果,那就很好,但如果需要均匀分布,则无法提供该效果。 - Simon
1
这是一个完美的机会,可以链接到概率论中最大的问题之一:Bertrand悖论 - naught101
2
编辑: 我建议对 rrandom.random() 部分取平方根,这样它将成为均匀分布。 - Ulf Aslak

8
第一个答案: 在继续之前,一个简单的解决方案是检查结果是否符合您的方程。
生成x、y(有方法可以随机选择范围)
检查((x-500)^2 + (y-500)^2 < 250000)是否为真 如果不是,则重新生成。
唯一的缺点是效率低下。
第二个答案:
或者,您可以做类似于利用黎曼和来近似积分的事情。通过将圆形分成许多矩形来近似圆形。 (矩形越多,精度越高),并对圆内的每个矩形使用您的矩形算法。

3
第一个答案的优点是简单明了,同时能正确提供(x,y)值的均匀分布。由于只有1-(0.25*PI)的配对会被拒绝,因此低效率相对较小。 - Simon
2
实际上,如果使用快速随机数生成器,这种方法很可能比“正确”方法更快,因为它避免了三角函数、根号、大数运算,并且平均只调用一次 random 函数。 - Veedrac

5
你需要采样(polar form):
r, theta = [math.sqrt(random.randint(0,500))*math.sqrt(500), 2*math.pi*random.random()]

你可以通过以下方式将极坐标 rtheta 转换为直角坐标 xy
x = 500 + r * math.cos(theta) 
y = 500 + r * math.sin(theta)

相关链接(虽然不是Python),但可以提供思路。


正如其他答案所指出的那样,这不会导致点数的均匀分布。 - naught101
@naught101 不会,它将在圆盘上生成均匀分布的点,注意我正在生成半径的平方根的均匀分布,而不是半径本身(这确实不会导致圆盘上的均匀分布)。 - vsoftco
啊,我明白你在做什么了。我认为如果你只是从单位圆中采样,然后再进行乘法和加法运算,可能会更清晰,而不是从半径为500的圆中采样。 - naught101

2

here's an example hope could help someone :).

randProba = lambda a: a/sum(a)
npoints = 5000 # points to chose from
r = 1 # radius of the circle

plt.figure(figsize=(5,5))
t = np.linspace(0, 2*np.pi, npoints, endpoint=False)
x = r * np.cos(t)
y = r * np.sin(t)
plt.scatter(x, y, c='0.8')

n = 2 # number of points to chose
t = np.linspace(0, 2*np.pi, npoints, endpoint=False)[np.random.choice(range(npoints), n, replace=False, p=randProba(np.random.random(npoints)))]
x = r * np.cos(t)
y = r * np.sin(t)

plt.scatter(x, y)

enter image description here


1

您可以使用拒绝抽样,在覆盖圆形的(2r)×(2r)正方形内生成一个随机点,重复此过程直到获得一个在圆内的点。


1
你可以使用下面的代码,如果想要了解更多,请访问https://programming.guide/random-point-within-circle.html
import random
import math
circle_x = 500
circle_y = 500
a = random.randint(0,500) * 2 * math.pi
r = 1 * math.sqrt(random.randint(0,500))
x = r * math.cos(a) + circle_x
y = r * math.sin(a) + circle_y

0

我会使用极坐标:

r_squared,theta = [random.randint(0,250000),2*math.pi*random.random()]

然后r始终小于或等于半径,theta始终在0到2*pi弧度之间。

由于r不在原点上,因此如果我理解正确,您将始终将其转换为以500, 500为中心的向量

x = 500 + math.sqrt(r_squared)*math.cos(theta) y = 500 + math.sqrt(r_squared)*math.sin(theta)

由于 this 的缘故,选择r_squared随机。


3
这种方法生成的(x,y)的分布将不是均匀的。 - Simon
x = 500 + r*math.cos(theta) y = 500 + r*math.sin(theta) 是这样的吗? - fiacre
@simon,我看到问题了:请将上面的代码修改为:r_squared, theta = [random.randint(0,250000), 2*math.pi*random.random()] 然后应用变换 x = 500 + math.sqrt(r_squared)*math.cos(theta) y = 500 + math.sqrt(r_squared)*math.sin(theta) - fiacre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接