2015-06-01 31 views
5

Mi chiedo come sia possibile generare numeri casuali visualizzati in una distribuzione circolare.Come generare punti casuali in una distribuzione circolare

sono in grado di generare punti casuali in una distribuzione rettangolare tale che i punti sono generati entro il quadrato (0 < = x < 1000, 0 < = y < 1000):

come andrei su per generare i punti all'interno di un cerchio tale che:

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

+2

Devono fare attenzione a come viene eseguito il calcolo, tuttavia. Se l'intenzione è di avere valori casuali (x, y) distribuiti uniformemente all'interno del cerchio, molti dei modi possibili per eseguire il calcolo non daranno quel risultato. – Simon

+0

http://mathworld.wolfram.com/DiskPointPicking.html – Veedrac

+2

Leggi [questo] (http://stats.stackexchange.com/questions/120527/how-to-generate-random-points-uniformly-distributed-in- un cerchio). – vsoftco

risposta

5

PRIMA RISPOSTA: Una soluzione semplice sarebbe quella di fare un controllo per vedere se il risultato soddisfa l'equazione prima di procedere.

Genera x, y (ci sono modi per randomizzare in una gamma selezionata)

Controllare se ((x-500)^2 + (y-500)^2 < 250000) è vero se non, rigenerare.

L'unico svantaggio sarebbe inefficienza.

seconda risposta:

Oppure, si potrebbe fare qualcosa di simile a somme di Riemann come per approssimare gli integrali. Approssimate la vostra circonferenza dividendolo in molti rettangoli. (più rettangoli, più precisi) e utilizza l'algoritmo del rettangolo per ciascun rettangolo all'interno della tua cerchia.

+3

La prima risposta ha il doppio merito di essere semplice e correttamente fornendo una distribuzione uniforme dei valori (x, y). L'inefficienza è relativamente piccola perché verrà rifiutata solo una frazione 1- (0,25 * PI) delle coppie. – Simon

+1

In realtà è abbastanza probabile che questo * sia * più veloce * di farlo "correttamente" se si utilizza un generatore di numeri casuali veloce poiché evita trigonometria, radici, numeri grandi e usa solo una chiamata a "random" in media. – Veedrac

4
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 * random.random() 
# calculating coordinates 
x = r * math.cos(alpha) + circle_x 
y = r * math.sin(alpha) + circle_y 

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

Nel tuo esempio circle_x è 500 come circle_y è. circle_r è 500.

Un'altra versione di calcolo distanza per ottenere uniformemente distribuita punti, sulla base di this answer

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

Non so se l'OP ne ha bisogno, ma questo * non * sarà una distribuzione uniforme. – andars

+2

Questo approccio produce valori distribuiti in modo non uniforme di (x, y) - saranno più concentrati nel centro rispetto al bordo del cerchio. Se questo è il risultato desiderato, va bene, ma se è richiesta una distribuzione uniforme, questo non lo fornirà. – Simon

+0

Questa è un'opportunità perfetta per collegare uno dei maggiori problemi della teoria della probabilità: il [paradosso di Bertrand] (https://en.wikipedia.org/wiki/Bertrand_paradox_ (probabilità)). – naught101

0

Vorrei usare le coordinate polari:

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

allora R è sempre minore o uguale al raggio, e theta sempre tra 0 e 2 * pi radianti.

Dal momento che r non è all'origine, sarete sempre convertirlo in un vettore centrato a 500, 500, se ho capito bene

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

Scegliere r_squared in modo casuale a causa di this

+3

La distribuzione di (x, y) prodotta da questo approccio non sarà uniforme. – Simon

+0

'x = 500 + r * math.cos (theta)' 'y = 500 + r * math.sin (theta)' Sì? – fiacre

+0

@simon, Vedo il problema: Modificare il codice sopra per essere: 'r_sqared, theta = [random.randint (0,250000), 2 * math.pi * random.random()]' Quindi applica una trasformazione 'x = 500 + math.sqrt (r_squared) * math.cos (theta)' 'y = 500 + math.sqrt (r_squared) * math.sin (theta)' – fiacre

4

Cosa è necessario campionare da (forma polare):

r, theta = [math.sqrt(random.randint(0,500))*math.sqrt(500), 2*math.pi*random.random()] 

È quindi possibile trasformare r e theta ritorna coordinate cartesiane x e y via

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

Related (anche se non Python), ma dà l'idea.

+0

Come notato su altre risposte, questo ha vinto ' t si traduce in una distribuzione uniforme dei punti. – naught101

+0

@ naught101 No, genererà punti distribuiti uniformemente sul disco, nota che sto generando un'uniforme della radice quadrata del raggio, non del raggio stesso (che in effetti non determinerà una distribuzione uniforme sul disco) . – vsoftco

+0

Ah, è vero, vedo quello che stai facendo. Penso che potrebbe essere più chiaro se hai appena campionato dal cerchio dell'unità, poi moltiplicato e aggiunto in seguito, piuttosto che campionare da un cerchio r = 500. – naught101

0

È possibile utilizzare rejection sampling, generare un punto casuale all'interno del quadrato (2r)×(2r) che copre il cerchio, ripetere fino a ottenere un punto all'interno del cerchio.

Problemi correlati