簡體   English   中英

如何在python中的開始和結束坐標之間獲得'n'個隨機點?

[英]How to get 'n' random points between start and end coordinates in python?

我有一個起始坐標 (x1,y1) 和一個結束坐標 (x2, y2)。 我想在開始和結束坐標之間生成“n”個隨機點,沒有任何重復。 如何用python做到這一點?

我知道一種簡單的方法是生成 'n' 個 x 值和 'n' 個 y 值。 所以我們得到 n*n 對,我在其中選擇“n”,沒有重復。 這樣我可能不會得到隨機點的均勻分布。 還有其他方法可以做到這一點嗎?

編輯:我需要由開始和結束坐標形成的矩形中的浮點坐標作為對角。

特爾;博士:

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 中,這意味着使用set而不是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函數,我得到了一致但稍微好一點的結果 - 我更喜歡第一個實現的清晰度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM