为了账号安全,请及时绑定邮箱和手机立即绑定

如何在python中获取起始坐标和结束坐标之间的“n”个随机点?

如何在python中获取起始坐标和结束坐标之间的“n”个随机点?

千万里不及你 2023-08-08 15:38:00
我有一个起始坐标(x1,y1)和一个结束坐标(x2,y2)。我想在开始和结束坐标之间生成“n”个随机点,没有任何重复。如何用 python 做到这一点?我知道一个简单的方法是生成“n”个 x 值和“n”个 y 值。所以我们得到 n*n 对,我在其中选择“n”,没有重复。这样我可能无法获得随机点的均匀分布。还有其他方法可以做到这一点吗?编辑:我需要由起始坐标和结束坐标作为对角形成的矩形中的浮点坐标。
查看完整描述

1 回答

?
回首忆惘然

TA贡献1847条经验 获得超11个赞

长话短说:


from random import uniform



def gen_coords(x1, y1, x2, y2, n):

    result = set()

    # loops for each addition, avoiding duplicates

    while len(result) < n:

        result.add((uniform(x1, x2), uniform(y1, y2)))

    return result

可以说,实际上:


from random import uniform



def gen_coords(x1, y1, x2, y2, n):

    return [(uniform(x1, x2), uniform(y1, y2)) for _ in range(n)]

考虑到碰撞的可能性很小。

假设“起始坐标和终止坐标之间”是指在笛卡尔坐标系(即平面、2D)中这两个角之间的矩形截面中。

并假设充分实现“均匀分布”,忽略浮点值的非均匀分布。(即,在任何相等长度的间隔上,浮点值的数量不是完全相同,也不是连续体中浮点值之间的恒定距离)

基本上有三种方法可以确保随机生成的点不重复:

  1. 从可能值的集合中选择它们,删除每个选择以避免再次选择;

  2. 在允许的空间内生成值,将每个选择与之前的选择进行检查,以避免添加重复项(并重新选择值,直到生成新值);

  3. 生成值并添加到集合中,直到达到所需的集合大小,生成后删除重复项(如果有)并重复该过程直至完成。

如果从中选取值的空间大小与目标集大小相似,第一个选项可能是一个不错的选择。然而,当在某些空间中选取具有随机浮点坐标的点时,这种情况不太可能发生。

第二种选择是最直接的,但如果目标集大小很大,则计算成本可能会很高,因为每个新选择都会导致更多比较。

第三种选择涉及更多一些,但在候选目标集完成之前避免进行比较,如果冲突的可能性很小,这当然是最佳选择。

作为第二个选择的变体,您可以选择一个目标数据结构,完全避免添加重复项,依靠语言/解释器比用该语言编写的任何算法更有效地执行检查。

在Python中,这意味着使用 aset而不是 a list,这是实现结果的最快方法,并且可能是您在第三个选项中检查重复项的方法 - 所以您也可以立即使用它并使用第二个选项的变体。

请注意,如果您尝试在选择函数的范围内创建大于选择函数域的集合,则第二个和第三个选项都有一个重大缺陷。但对于给定的问题,除了非常大的“n”之外,这是不可能的。

解决方案(将第二个选项与第三个选项进行比较):

from random import uniform

from timeit import timeit



def pick_coords_restricted(x1, y1, x2, y2, n):

    result = set()

    # loops for each addition, avoiding duplicates

    while len(result) < n:

        result.add((uniform(x1, x2), uniform(y1, y2)))

    return result



def pick_coords_checked(x1, y1, x2, y2, n):

    result = []

    # loops once for attempt, checking after each iteration

    while len(set(result)) < n:

        if len(result) > 0:

            result = list(set(result))

            result += [(uniform(x1, x2), uniform(y1, y2)) for _ in range(n - len(result))]

        else:

            result = [(uniform(x1, x2), uniform(y1, y2)) for _ in range(n)]

    return result



print(timeit(lambda: pick_coords_restricted(0, 0, 1, 1, 1000), number=10000))

print(timeit(lambda: pick_coords_checked(0, 0, 1, 1, 1000), number=10000))

结果(在我的硬件上):


4.3799341

3.9363368000000003

我得到了一致的、但稍微更好的函数结果pick_coords_checked——我赞成第一个实现的清晰度。


查看完整回答
反对 回复 2023-08-08
  • 1 回答
  • 0 关注
  • 98 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信