원 안에 임의의 점을 생성합니다 (균일하게)


212

반지름 R 의 원 안에 균일하게 임의의 점을 생성해야합니다 .

나는 간격 [0 ... 2π)에서 균일하게 임의의 각도를 선택하고 간격 (0 ... R ) 에서 균일하게 임의의 반경을 선택함으로써 주어진 두 개의 점 때문에 중심을 향한 더 많은 점으로 끝날 것이라는 것을 알고 있습니다. 반지름이 작을수록 반지름이 작은 점이 반지름이 큰 점보다 서로 더 가깝습니다.

여기 에서 블로그 항목을 찾았 지만 그의 추론을 이해하지 못합니다. 나는 그것이 옳다고 생각하지만 , 그가 (2 / R 2 ) x r 을 얻는 곳 과 그가 어떻게 최종 솔루션을 도출하는지 이해하고 싶습니다 .


업데이트 : 이 질문을 게시 한 지 7 년이 지난 지금도 여전히 제곱근 알고리즘의 수학에 관한 실제 질문에 대한 만족스러운 답변을받지 못했습니다. 그래서 답을 직접 쓰는 데 하루를 보냈습니다. 내 답변에 연결합니다 .


18
거부 샘플링의 단점은 실제로 큰 문제입니까? 예상되는 시도 횟수는 4 / π ≈ 1.27이며, k 시도 이상이 필요할 확률은 (1-π / 4) ^ k입니다. 들면 K = 20 , 이는 ≈ 0.00000000000004을이고 K = 50 대 10 ^의 순서이다 {- 34}. 당신은 그 확률을 언제든지 취할 수 있습니다; 당신은 잘 할 것입니다.
ShreevatsaR

3
실제로 거부 샘플링은 종료를 보장합니다. 알고리즘이 종료되지 않을 확률은 무한히 낮습니다 (정확하게는 0).
자레드 닐슨

2
제 생각에, 거부 샘플링의 단점은 거부를 피하는 샘플링 방법의 사용 편의성에 비례합니다. 이 경우 거부없이 샘플링하는 것이 간단하기 때문에 단점이 중요합니다.
spex

4
@spex 실제로, 거부 기술은 초월 함수 평가가 필요하지 않기 때문에 더 빠릅니다.
pjs

2
(계속) 기각 : 0.52 초 모두 동일한 평균과 표준 편차를 나타 냈습니다 (그림 3까지). 예상대로, 거부 샘플링은 시간의 27 % (4 / pi-1)에 실패했기 때문에 btilly보다 27 % 더 많은 난수가 필요하지만 sigfpe보다 15 % 더 적습니다. 이는 랜덤이 생성하는 데 비용이 많이 들지 않는 한 pjs와 다른 사람들이 거부 샘플링을 사용하는 것이 최선의 방법이라는 의견을 확인시켜줍니다.
피터 데이비슨

답변:


189

아르키메데스처럼 접근 해보자.

삼각형 ABC에서 어떻게 점을 균일하게 생성 할 수 있습니까? | AB | = | BC |? 평행 사변형 ABCD로 확장하여이를 쉽게 만들어 봅시다. ABCD에서 점을 균일하게 생성하는 것은 쉽습니다. AB에서 랜덤 포인트 X와 BC에서 Y를 균일하게 선택하고 XBYZ가 평행 사변형이되도록 Z를 선택합니다. 원래 삼각형에서 균일하게 선택된 점을 얻으려면 ADC에 나타나는 점을 AC를 따라 ABC로 다시 접습니다.

이제 원을 생각해보십시오. 한계에서 우리는 그것을 원점에 B가 있고 원주에 A와 C가 서로 가깝게 가까운 무한히 많은 이등변 삼각형 ABC라고 생각할 수 있습니다. 각도 세타를 선택하면이 삼각형 중 하나를 선택할 수 있습니다. 이제는 은색 ABC에서 점을 선택하여 중심으로부터 거리를 생성해야합니다. 다시 ABCD로 확장합니다. 여기서 D는 이제 원 중심에서 반지름의 두 배입니다.

위의 방법을 사용하면 ABCD에서 임의의 점을 쉽게 선택할 수 있습니다. AB에서 임의의 지점을 선택하십시오. BC에서 무작위로 임의의 지점을 선택하십시오. 즉. 중심으로부터의 거리를 제공하는 [0, R]에서 한 쌍의 난수 x와 y를 균일하게 선택하십시오. 우리의 삼각형은 얇은 은색이므로 AB와 BC는 본질적으로 평행합니다. 따라서 점 Z는 단순히 원점으로부터의 거리 x + y입니다. x + y> R이면 다시 접습니다.

다음은 R = 1에 대한 완전한 알고리즘입니다. 나는 그것이 매우 간단하다는 데 동의하기를 바랍니다. Trig을 사용하지만 random()거부 샘플링과 달리 소요 시간과 필요한 호출 수를 보장 할 수 있습니다 .

t = 2*pi*random()
u = random()+random()
r = if u>1 then 2-u else u
[r*cos(t), r*sin(t)]

여기 Mathematica에 있습니다.

f[] := Block[{u, t, r},
  u = Random[] + Random[];
  t = Random[] 2 Pi;
  r = If[u > 1, 2 - u, u];
  {r Cos[t], r Sin[t]}
]

ListPlot[Table[f[], {10000}], AspectRatio -> Automatic]

여기에 이미지 설명을 입력하십시오


6
@Karelzarath 나는 한쪽 끝이 다른 쪽 끝보다 여전히 넓은 무한히 얇은 삼각형의 반 직관적 인 개념을 좋아합니다. :-) 정답을 얻습니다.
sigfpe

2
@hammar 그것이 n 차원으로 일반화되는지 확실하지 않습니다. 그러나 3d에서는 Archimedes의 다른 결과를 사용할 수 있습니다! "모자 상자"정리를 사용하여 원통에 점을 생성 한 다음 (쉽게!) 구에 다시 매핑합니다. 그것은 방향을 제시합니다. 이제 random()+random()+random()좀 더 복잡한 접힘 (즉, 육면체에 무한히 평행 한 육면체의 6 방향 접힘)을 사용하십시오. 이것이 좋은 방법이라고 확신하지 못합니다.
sigfpe

2
random () + random ()과 2 * random ()의 차이를 알아내는 데 1 분이
걸렸다 고

3
@Tharwen 원 안에 반지름 0.0-0.1보다 반지름 0.9-1.0에 더 많은 점이 있는지 확인하십시오. random () + random ()은 반경이 1.0 정도일 가능성이 높지만 0.0-2.0 범위에 있습니다. 접 으면 1.0 정도일 가능성이 높으며 항상 0.0-1.0 범위에 있습니다. 또한이 의견의 첫 번째 문장에 필요한 비율입니다. 반으로 줄이면 0.5 점 부근에서 더 많은 숫자가 나오고 이는 잘못된 것입니다.
sigfpe

2
@Tharwen 두 가지 체계를 모두 사용하여 난수를 생성하고 얻는 결과를 확인하십시오. 2 * random ()은 0에서 2까지의 범위에 균일하게 분포 된 숫자를 제공합니다. random () + random ()은 0에서 2까지의 숫자를 제공하지만 (일반적으로) 0.0 또는 2.0에 가까운 것보다 1.0 근처에 더 많은 숫자가 있습니다. 두 주사위를 굴리면 합산이 다른 숫자보다 7을 줄 가능성이 높습니다.
sigfpe

133

반경 R 의 원 안에 임의의 점을 생성하는 방법 :

r = R * sqrt(random())
theta = random() * 2 * PI

( random()0과 1 사이의 값을 균일하게 부여 한다고 가정 )

이것을 직교 좌표로 변환하려면 할 수 있습니다

x = centerX + r * cos(theta)
y = centerY + r * sin(theta)


sqrt(random())?

이어지는 수학을 보자 sqrt(random()) . 우리가 단위 원으로 작업하고 있다는 것을 간단하게 가정하십시오 (예 : R = 1).

점 사이의 평균 거리는 중심에서 얼마나 떨어져 있는지에 관계없이 동일해야합니다. 예를 들어 원주 2의 원 둘레를 보면 원주 1의 원 둘레 점 수의 두 배를 발견해야합니다.


                

원의 둘레 (2π r )가 r 과 함께 선형으로 성장 하기 때문에 임의의 점 수가 r 와 함께 선형으로 증가해야합니다 . 즉, 원하는 확률 밀도 함수 (PDF)가 선형으로 증가합니다. PDF의 면적이 1이고 최대 반지름이 1이므로


                

따라서 임의의 값의 원하는 밀도가 어떻게 보이는지 알고 있습니다. 지금: 우리가 가진 모든 것이 0과 1 사이의 균일 한 임의의 값일 때 어떻게 이러한 임의의 값을 생성합니까?

우리는라는 속임수를 사용합니다 역변환 샘플링

  1. PDF에서 누적 분포 함수 (CDF)를
  2. y = x를 따라 이것을 미러링
  3. 결과 함수를 0과 1 사이의 균일 한 값에 적용하십시오.

복잡한 소리? 직관을 전달하는 작은 트랙이있는 인용구를 삽입하겠습니다.

다음 분포를 사용하여 임의의 점을 생성한다고 가정합니다.

                

그건

  • 1과 2 사이의 점의 1/5
  • 점의 4/5는 2에서 3 사이에서 균일합니다.

CDF는 이름에서 알 수 있듯이 PDF의 누적 버전입니다. 직관적으로 : PDF ( x )는 x 의 난수 값 설명 하지만 CDF ( x )는 x보다 작은 난수 값을 설명합니다 .

이 경우 CDF는 다음과 같습니다.

                

이것이 어떻게 유용한 지 보려면, 균일하게 분포 된 높이에서 총알을 왼쪽에서 오른쪽으로 쏘는다고 상상해보십시오. 총알이 선에 부딪히면 땅에 떨어집니다.

                

지상의 총알 밀도가 원하는 분포와 어떻게 일치하는지 확인하십시오! 거의 다 왔어!

문제는이 함수의 경우 y 축이 출력 이고 x 축이 입력이라는 것입니다 입니다. 우리는 "땅에서 총알을 똑바로 쏴"만 할 수 있습니다! 우리는 역함수가 필요합니다!

이것이 우리가 모든 것을 반영하는 이유입니다. xy가 되고 yx 가됩니다 :

                

CDF -1 이라고합니다 . 원하는 분포에 따라 값을 얻기 위해 CDF -1 (random ())을 사용합니다.

… 따라서 PDF가 2 x 인 임의의 반경 값 생성으로 돌아갑니다. .

1 단계 : CDF를 작성하십시오.

실수로 작업하기 때문에 CDF는 PDF의 필수 요소로 표시됩니다.

CDF ( x ) = ∫ 2 x = x 2

2 단계 : y = x를 따라 CDF를 미러링합니다 .

수학적으로이 교환으로 귀결 XY를 하고 대한 해결 Y :

CDF :      y = x 2
스왑 :    x = y 2
풀기 :    y = √ x
CDF -1 :   y = √ x

3 단계 : 결과 함수를 0과 1 사이의 균일 한 값에 적용

CDF -1 (random ()) = √random ()

우리가 도출 한 것은 다음과 같습니다. :-)


이 알고리즘은 링에서 점을 효율적으로 생성하는 데 사용할 수 있습니다.
Ivan Kovtun

반지에? 고정 반경처럼? 귀하의 질문을 이해하는지 확실하지 않지만 반경이 고정되어 있으면 각도를 무작위로 지정하면됩니다.
aioobe

2
나는 두 개의 동심원으로 둘러싸인 Annulus 대신에 간단한 단어 "Ring"을 사용하려고했습니다. 이 경우 거부 알고리즘이 효과적이지 않고 첫 번째 상위 알고리즘을 일반화하기가 어렵습니다. 반경이 하나 인 코너 케이스도 알고리즘으로 덮여 있습니다. min_radius == max_radius 인 경우에도 항상 반경을 sqrt (random (min_radius ^ 2, max_radius ^ 2))로 생성합니다.
Ivan Kovtun

1
오, 좋아! 명확하게하기 위해, 당신이 말할 때 random(min_radius², max_radius²), 당신 평균 무엇인가에 해당 할 random() * (max_radius² - min_radius²) + min_radius²random()반환 0과 1 사이의 균일 한 값?
aioobe

예, 이것이 정확히 의미하는 것입니다 : radius = sqrt (random () * (max_radius²-min_radius²) + min_radius²).
Ivan Kovtun

27

여기에 빠르고 간단한 해결책이 있습니다.

즉, 범위 (0, 1) 두 개의 난수를 선택 a하고 b. 인 경우 b < a교체하십시오. 요점은 (b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b))입니다.

이 솔루션에 대해 다음과 같이 생각할 수 있습니다. 원을 가져 와서 자른 다음 곧게 펴면 직각 삼각형이 나타납니다. 그 삼각형의 다운 스케일, 당신은에서 삼각형이 줄 (0, 0)(1, 0)(1, 1)에 다시와 (0, 0). 이러한 모든 변환은 밀도를 균일하게 변경합니다. 당신이 한 일은 삼각형에서 임의의 점을 균일하게 고르고 원에서 점을 얻기 위해 과정을 뒤집 었습니다.


나는이 반경 좌표 분할해야 않았지만이, 어떤 이유로, 그렇지 않으면 ^ 2 R의 원 안에 있어요, 나에게 허용 대답보다 훨씬 더 균일 한 분포를 제공합니다
그렉 Zaal

3
고마워요, 이것은 Java 코드입니다. 어쩌면 누군가 유용 할 것입니다. float random1 = MathUtils.random (); float random2 = MathUtils.random (); float randomXPoint = random2 * radius MathUtils.cos (MathUtils.PI2 * random1 / random2); float randomYPoint = random2 * radius MathUtils.sin (MathUtils.PI2 * random1 / random2);
Tony Ceralva

아주 좋아! 나는 포인트를 중앙 집중화 할 확률이 더 높다는 아이디어를 좋아합니다. 따라서 우리가 b < a이것을 달성 할 수 있을 때 교환하지 않으면 ! 예를 들어 자바 스크립트 jsfiddle.net/b0sb5ogL/1
Guilherme

귀하의 솔루션이 나쁘다고 생각합니다. 균일 한 결과를 제공하지 않습니다. 이 스크린 샷을 확인하십시오 prntscr.com/fizxgc
bolec_kolec

4
원을 자르고 똑 바르게하는 방법을 조금 더 설명해 주시겠습니까?
kec

21

따라서 대신 따기의 반지름의 제곱에 반비례의 포인트 밀도를 참고 r에서 [0, r_max]에서 선택, [0, r_max^2]다음, 당신의 좌표로 계산 :

x = sqrt(r) * cos(angle)
y = sqrt(r) * sin(angle)

이렇게하면 디스크에서 균일 한 점 분포가 제공됩니다.

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


12

이런 식으로 생각하십시오. 하나의 축이 반지름이고 다른 하나가 각도 인 사각형이 있고이 사각형 내부의 반지름 0 근처에있는 점을 사용하는 경우 원점에 매우 가깝습니다 (원에 가깝습니다). 반경 R 근처의 점은 모두 원의 가장자리 근처에 있습니다 (즉, 서로 멀리 떨어져 있음).

이렇게하면 왜이 동작이 발생하는지 알 수 있습니다.

해당 링크에서 파생 된 요소는 원에 매핑 된 반지름에 의존하지 않도록 사각형의 해당 영역을 얼마나 조정해야하는지 알려줍니다.

편집 : 그래서 그가 당신이 공유하는 링크에 쓴 것은 "그것은 누적 분포의 역수를 계산함으로써 쉽게 할 수 있고, 우리는 r :을 얻는 것입니다."입니다.

기본 전제는 여기에서 원하는 확률 밀도 함수의 누적 분포 함수의 역함수로 유니폼을 매핑하여 유니폼에서 원하는 분포로 변수를 만들 수 있다는 것입니다. 왜? 당분간은 당연한 것으로 여기지만 사실입니다.

다음은 수학에 대한 직관적 인 설명입니다. r에 대한 밀도 함수 f (r)은 r 자체에 비례해야합니다. 이 사실을 이해하는 것은 기본 미적분학 서적의 일부입니다. 극지방 요소에 대한 섹션을 참조하십시오. 다른 포스터들도 이것을 언급했습니다.

그래서 우리는 그것을 f (r) = C * r이라고 부릅니다.

이것은 대부분의 작업으로 밝혀졌습니다. 이제, f (r)은 확률 밀도 여야하므로, 간격 (0, R)에 걸쳐 f (r)을 적분함으로써 C = 2 / R ^ 2를 얻는다는 것을 쉽게 알 수 있습니다. .)

따라서 f (r) = 2 * r / R ^ 2

자, 이것이 링크에서 수식을 얻는 방법입니다.

그런 다음 마지막 부분은 (0,1)의 균일 한 랜덤 변수 u에서 나옵니다.이 원하는 밀도 f (r)에서 누적 분포 함수의 역함수로 매핑해야합니다. 이것이 왜 그런지를 이해하려면 Papoulis와 같은 고급 확률 텍스트를 찾거나 직접 파생해야합니다.

f (r)을 적분하면 F (r) = r ^ 2 / R ^ 2

이것의 역함수를 구하려면 u = r ^ 2 / R ^ 2를 설정하고 r을 구하면 r = R * sqrt (u)가됩니다.

이것은 완전히 직관적으로도 의미가 있으며, u = 0은 r = 0에 매핑되어야합니다. 또한 u = 1 shoudl은 r = R에 매핑됩니다.


10

순진한 솔루션이 작동하지 않는 이유는 원 중심에 가까운 점에 높은 확률 밀도를 제공하기 때문입니다. 즉, 반지름이 r / 2 인 원은 선택된 점을 얻을 확률이 r / 2이지만 면적 (점 수) pi * r ^ 2 / 4를 갖습니다.

따라서 반지름 확률 밀도에 다음과 같은 속성이 있어야합니다.

주어진 r보다 작거나 같은 반경을 선택할 확률은 반경이 r 인 원의 면적에 비례해야합니다. (우리는 점에 균일 한 분포를 원하고 더 큰 영역은 더 많은 점을 의미하기 때문에)

다시 말해, 우리는 [0, r] 사이의 반지름을 선택할 확률이 원의 전체 영역에서 차지하는 비율과 같기를 원합니다. 총 원 면적은 pi * R ^ 2이고 반경이 r 인 원의 면적은 pi * r ^ 2입니다. 따라서 [0, r] 사이의 반지름을 (pi * r ^ 2) / (pi * R ^ 2) = r ^ 2 / R ^ 2로 선택할 확률을 원합니다.

이제 수학이 온다 :

[0, r] 사이의 반지름을 선택할 확률은 p에서 (r) dr의 0에서 r까지의 적분입니다 (작은 반지름의 모든 확률을 추가하기 때문입니다). 따라서 우리는 integral (p (r) dr) = r ^ 2 / R ^ 2를 원합니다. 우리는 R ^ 2가 상수라는 것을 분명히 알 수 있습니다. 그래서 우리가해야 할 일은 r ^ 2와 같은 것을 줄 때 p (r)를 알아내는 것입니다. 대답은 분명히 r * 상수입니다. 적분 (r * 상수 dr) = r ^ 2 / 2 * 상수. 이것은 r ^ 2 / R ^ 2와 같아야하므로 상수 = 2 / R ^ 2입니다. 따라서 확률 분포 p (r) = r * 2 / R ^ 2

참고 : 문제에 대해보다 직관적으로 생각할 수있는 또 다른 방법은 반경 ra의 각 확률 원이 원주에있는 점 수의 비율과 동일하게하려고한다는 것을 상상하는 것입니다. 따라서 반지름 r을 갖는 원은 원주에 2 * pi * r "점"을 가질 것이다. 총 포인트 수는 pi * R ^ 2입니다. 따라서 원 ra의 확률은 (2 * pi * r) / (pi * R ^ 2) = 2 * r / R ^ 2와 같아야합니다. 이것은 이해하기 쉽고 직관적이지만 수학적으로 들리는 것은 아닙니다.


9

ρ (반지름) 및 φ (방위각)를 원 안의 임의의 점의 극좌표에 해당하는 두 개의 임의 변수로 둡니다. 점이 균일하게 분포되면 ρ와 φ의 분포 함수는 무엇입니까?

r : 0 <r <R의 경우 반경 좌표 ρ의 확률이 r보다 작을 때 r은

P [ρ <r] = P [점은 반경의 원 안에 있습니다 r] = S1 / S0 = (r / R) 2

여기서 S1과 S0은 각각 반경 r과 R의 원의 영역입니다. 따라서 CDF는 다음과 같이 주어질 수 있습니다.

          0          if r<=0
  CDF =   (r/R)**2   if 0 < r <= R
          1          if r > R

그리고 PDF :

PDF = d/dr(CDF) = 2 * (r/R**2) (0 < r <= R).

R = 1의 경우 랜덤 변수 sqrt (X)가 X가 [0, 1에서 균일 한 경우]이 정확한 CDF를 갖습니다 (P [sqrt (X) <y] = P [x <y ** 2] = y *). 0 <y <= 1의 경우 * 2).

φ의 분포는 분명히 0에서 2 * π까지 균일합니다. 이제 임의의 극좌표를 생성하고 삼각 방정식을 사용하여 직교 좌표로 변환 할 수 있습니다.

x = ρ * cos(φ)
y = ρ * sin(φ)

R = 1에 대한 파이썬 코드 게시에 저항 할 수 없습니다.

from matplotlib import pyplot as plt
import numpy as np

rho = np.sqrt(np.random.uniform(0, 1, 5000))
phi = np.random.uniform(0, 2*np.pi, 5000)

x = rho * np.cos(phi)
y = rho * np.sin(phi)

plt.scatter(x, y, s = 4)

당신은 얻을 것이다

여기에 이미지 설명을 입력하십시오


7

그것은 실제로 '균일하게 무작위'라는 것이 무엇을 의미하는지에 달려 있습니다. 이것은 미묘한 점이며 여기 위키 페이지에서 자세한 내용을 볼 수 있습니다 : http://en.wikipedia.org/wiki/Bertrand_paradox_%28probability%29 )에서 여기서 동일한 문제는 '균일하게 임의적 인' 다른 답변!

점을 선택하는 방법에 따라 분포는 일부 에서 균일하게 임의적이지만 분포가 다를 수 있습니다. 의미 .

블로그 항목은 다음과 같은 의미에서 균일하게 무작위로 만들려고하는 것처럼 보입니다. 동일한 중심을 가진 원의 하위 원을 가져 가면 해당 지역에 포인트가 떨어지는 확률은 지역. 그것은 2D 영역에 대해 정의 된 영역을 가진 '균일하게 임의적 인'표준 해석을 따르려고 시도하고 있습니다 . 영역이 잘 정의 된 영역에서 떨어지는 지점의 확률은 해당 영역의 영역에 비례합니다.


5
또는 오히려 지점에서 떨어지는 확률 어떤 영역이 가정 - 임의의 영역은 영역의 면적에 비례 하는 영역이있다 .
ShreevatsaR

@Shree : 맞습니다. 이것은 괄호 안의 진술로 암시 된 것입니다. 감사합니다. btw, 블로그에 관해서는 임의의 영역이 비례 확률을 제공한다는 실제적인 증거는 없었기 때문에 나는 그렇게 표현했습니다.

6

다음은 num원의 반지름에서 임의의 점 을 생성하는 Python 코드 입니다 rad.

import matplotlib.pyplot as plt
import numpy as np
rad = 10
num = 1000

t = np.random.uniform(0.0, 2.0*np.pi, num)
r = rad * np.sqrt(np.random.uniform(0.0, 1.0, num))
x = r * np.cos(t)
y = r * np.sin(t)

plt.plot(x, y, "ro", ms=1)
plt.axis([-15, 15, -15, 15])
plt.show()

1
왜 안돼 r = np.sqrt(np.random.uniform(0.0, rad**2, num))?

4

이 경우 극좌표를 사용하는 것이 문제를 복잡하게하는 방법이라고 생각합니다. 길이가 2R 인 정사각형으로 임의의 점을 선택한 다음 점을 선택하면 훨씬 쉬울 것 (x,y)입니다 x^2+y^2<=R^2.


당신은 x ^ 2 + y ^ 2 <= R ^ 2라고 생각합니다.
sigfpe

1
이것은 거부 샘플링입니다. 괜찮지 만 계산 시간이 다소 다르므로 문제가 될 수 있습니다.
Steve Bennett

모든 사각형은 4면입니다.
xaxxon

이 알고리즘은 제곱근이나 sin / cos 계산과 관련된 것보다 더 효율적입니다. 정사각형의 21.5 % 미만을 거부합니다.
Ivan Kovtun

3

Java 솔루션 및 배포 예제 (2000 점)

public void getRandomPointInCircle() {
    double t = 2 * Math.PI * Math.random();
    double r = Math.sqrt(Math.random());
    double x = r * Math.cos(t);
    double y = r * Math.sin(t);
    System.out.println(x);
    System.out.println(y);
}

분포 2000 포인트

이전 솔루션을 기반으로 https : //.com/a/5838055/5224246 @sigfpe


2

먼저 cdf [x]를 생성합니다.

점이 원의 중심으로부터 거리 x보다 작을 확률. 원의 반지름이 R이라고 가정합니다.

x가 0이면 분명히 cdf [0] = 0

x가 R이면 cdf [R] = 1

분명히 x = r이면 cdf [r] = (Pi r ^ 2) / (Pi R ^ 2)

원의 각 "작은 영역"은 같은 확률로 선택 될 수 있기 때문에 해당 영역에 비례 할 확률이 있습니다. 그리고 원의 중심으로부터 거리 x가 주어진 영역은 Pi r ^ 2입니다.

파이는 서로 상쇄되기 때문에 cdf [x] = x ^ 2 / R ^ 2

cdf [x] = x ^ 2 / R ^ 2가 있습니다. 여기서 x는 0에서 R로갑니다

그래서 우리는 x를 풀고

R^2 cdf[x] = x^2

x = R Sqrt[ cdf[x] ]

cdf를 0에서 1까지의 난수로 대체 할 수 있습니다.

x = R Sqrt[ RandomReal[{0,1}] ]

드디어

r = R Sqrt[  RandomReal[{0,1}] ];
theta = 360 deg * RandomReal[{0,1}];
{r,theta}

우리는 극좌표를 얻습니다 {0.601168 R, 311.915 deg}


1

반지름과 해당 반지름 근처에있는 포인트 수 사이에는 선형 관계가 있으므로 반지름 근처의 데이터 포인트 수에 r비례 하는 반지름 분포를 사용해야합니다 r.


1

나는이 방법을 한 번 사용했습니다 : 이것은 완전히 최적화되지 않을 수 있습니다 (즉, 큰 원에는 사용할 수없는 점 배열을 사용합니다). 그러나 무작위 분포는 충분합니다. 행렬 생성을 건너 뛰고 원하는 경우 직접 그릴 수 있습니다. 이 방법은 원 안에있는 사각형의 모든 점을 무작위로 만드는 것입니다.

bool[,] getMatrix(System.Drawing.Rectangle r) {
    bool[,] matrix = new bool[r.Width, r.Height];
    return matrix;
}

void fillMatrix(ref bool[,] matrix, Vector center) {
    double radius = center.X;
    Random r = new Random();
    for (int y = 0; y < matrix.GetLength(0); y++) {
        for (int x = 0; x < matrix.GetLength(1); x++)
        {
            double distance = (center - new Vector(x, y)).Length;
            if (distance < radius) {
                matrix[x, y] = r.NextDouble() > 0.5;
            }
        }
    }

}

private void drawMatrix(Vector centerPoint, double radius, bool[,] matrix) {
    var g = this.CreateGraphics();

    Bitmap pixel = new Bitmap(1,1);
    pixel.SetPixel(0, 0, Color.Black);

    for (int y = 0; y < matrix.GetLength(0); y++)
    {
        for (int x = 0; x < matrix.GetLength(1); x++)
        {
            if (matrix[x, y]) {
                g.DrawImage(pixel, new PointF((float)(centerPoint.X - radius + x), (float)(centerPoint.Y - radius + y)));
            }
        }
    }

    g.Dispose();
}

private void button1_Click(object sender, EventArgs e)
{
    System.Drawing.Rectangle r = new System.Drawing.Rectangle(100,100,200,200);
    double radius = r.Width / 2;
    Vector center = new Vector(r.Left + radius, r.Top + radius);
    Vector normalizedCenter = new Vector(radius, radius);
    bool[,] matrix = getMatrix(r);
    fillMatrix(ref matrix, normalizedCenter);
    drawMatrix(center, radius, matrix);
}

여기에 이미지 설명을 입력하십시오


3
배포판은 "충분하지 않습니다". 주어진 임의의 정의에 대해 무작위이거나 무작위가 아닙니다. 당신의 대답은 비스듬합니다 : 당신은 당신의 코드에 주석을 달거나 어떻게 코드에 도달하는지 설명하지 않습니다. 비스듬한 대답은 따르기가 어렵고 신뢰하기가 어렵습니다.
Richard

1

원의 영역 요소는 dA = rdr * dphi입니다. 그 추가 요소 r은 ar과 phi를 무작위로 선택하려는 아이디어를 파괴했습니다. phi는 평평하게 분포되어 있지만, r은 그렇지 않고 1 / r로 평평합니다 (즉, "황소의 눈"보다 경계에 부딪 칠 가능성이 높습니다).

따라서 평평한 분포에서 원 픽 파이에 고르게 분포 된 점을 생성하고 1 / r 분포에서 r을 선택하십시오.

또는 Mehrdad에서 제안한 Monte Carlo 방법을 사용하십시오.

편집하다

1 / r에서 임의의 r 플랫을 선택하려면 간격 [1 / R, 무한대]에서 임의의 x를 선택하고 r = 1 / x를 계산할 수 있습니다. 그런 다음 r은 1 / r로 평평하게 분포됩니다.

랜덤 phi를 계산하려면 구간 [0, 1]에서 랜덤 x를 선택하고 phi = 2 * pi * x를 계산하십시오.


"1 / r 분포" 에서 r 을 정확히 어떻게 선택 합니까?
aioobe

0

이 질문이 이미 주어진 모든 대답을 가진 새로운 솔루션에 대해 열려 있는지는 모르겠지만 정확히 같은 질문에 직면했습니다. 나는 해결책을 찾기 위해 나 자신과 "추론"을하려고 노력했다. 일부는 이미 여기에서 제안한 것과 같을 수도 있지만 어쨌든 여기 있습니다.

동일한 dr를 가정하면 원 표면의 두 요소가 동일하기 위해서는 dtheta1 / dtheta2 = r2 / r1이 있어야합니다. 해당 요소에 대한 확률의 표현을 P (r, theta) = P {r1 <r <r1 + dr, theta1 <theta <theta + dtheta1} = f (r, theta) * dr * dtheta1로 쓰고 확률 (r1과 r2의 경우)이 같으면 (r과 theta가 독립적이라고 가정) f (r1) / r1 = f (r2) / r2 = 상수에 도달하면 f (r) = c * r이됩니다. 그리고 상수 c를 결정하는 나머지는 f (r)가 PDF 인 조건에서 따릅니다.


dtheta1 / dtheta2 = r2 / r1로 시작하는 재미있는 접근법. 그 방정식을 어떻게 만들 었는지 자세히 설명해 주시겠습니까?
aioobe

다른 사람들이 언급했듯이 (예를 들어, 혼크) 원 표면의 차동 요소는 r dr dtheta 로 주어 지므로 r1 = r2라고 가정하면 dr1 * dtheta1 = dr2 * dtheta2가되고 나머지는 다음과 같습니다. .
arsaKasra 2016 년

0

프로그래머 솔루션 :

  • 비트 맵 (부울 값의 행렬)을 만듭니다. 원하는만큼 클 수 있습니다.
  • 해당 비트 맵에 원을 그립니다.
  • 원 점의 룩업 테이블을 만듭니다.
  • 이 룩업 테이블에서 임의의 인덱스를 선택하십시오.
const int RADIUS = 64;
const int MATRIX_SIZE = RADIUS * 2;

bool matrix[MATRIX_SIZE][MATRIX_SIZE] = {0};

struct Point { int x; int y; };

Point lookupTable[MATRIX_SIZE * MATRIX_SIZE];

void init()
{
  int numberOfOnBits = 0;

  for (int x = 0 ; x < MATRIX_SIZE ; ++x)
  {
    for (int y = 0 ; y < MATRIX_SIZE ; ++y)
    {
      if (x * x + y * y < RADIUS * RADIUS) 
      {
        matrix[x][y] = true;

        loopUpTable[numberOfOnBits].x = x;
        loopUpTable[numberOfOnBits].y = y;

        ++numberOfOnBits;

      } // if
    } // for
  } // for
} // ()

Point choose()
{
  int randomIndex = randomInt(numberOfBits);

  return loopUpTable[randomIndex];
} // ()

비트 맵은 논리 설명에만 필요합니다. 이것은 비트 맵이없는 코드입니다.

const int RADIUS = 64;
const int MATRIX_SIZE = RADIUS * 2;

struct Point { int x; int y; };

Point lookupTable[MATRIX_SIZE * MATRIX_SIZE];

void init()
{
  int numberOfOnBits = 0;

  for (int x = 0 ; x < MATRIX_SIZE ; ++x)
  {
    for (int y = 0 ; y < MATRIX_SIZE ; ++y)
    {
      if (x * x + y * y < RADIUS * RADIUS) 
      {
        loopUpTable[numberOfOnBits].x = x;
        loopUpTable[numberOfOnBits].y = y;

        ++numberOfOnBits;
      } // if
    } // for
  } // for
} // ()

Point choose()
{
  int randomIndex = randomInt(numberOfBits);

  return loopUpTable[randomIndex];
} // ()

0

나는 여전히 정확한 '(2 / R2) × r'에 대해 확신하지 못하지만, 명백한 것은 주어진 단위 'dr'에 분포되어야하는 점의 수입니다. 즉, r의 증가는 r이 아니라 r2에 비례합니다.

이 방법으로 확인하십시오 ... 각도 세타에서 r (0.1r ~ 0.2r) 사이의 포인트 수, 즉 표준 생성을 사용하는 경우 r의 분수와 r (0.6r ~ 0.7r) 사이의 포인트 수는 동일합니다. 두 간격 사이의 차이는 0.1r에 불과하기 때문입니다. 그러나 포인트 (0.6r ~ 0.7r) 사이의 영역이 0.1r ~ 0.2r 사이의 영역보다 훨씬 크기 때문에 동일한 수의 포인트가 넓은 영역에서 드문 간격으로 배치되므로 이미 알고 있다고 가정합니다. 임의의 점을 생성하는 것은 선형이 아니라 2 차적이어야합니다. (주어진 단위 'dr'에 분배해야하는 점의 수 (즉, r의 증가는 r이 아니라 r2에 비례 할 것이므로)),이 경우에는 우리가 가진 델타 (0.


피타고라스 정리를 가장 먼저 언급 한 사람입니다. 나는 당신이 당신의 설명을 뒷받침하여 그림을 두 개로 확장 할 수 있다면 좋을 것입니다. 나는 지금 서있는대로 다음과 같은
어려움을 겪고

@aioobe 나는 답을 바꾸려고 노력했다. 필요한 경우 다이어그램을 추가 할 수있다.)
cheesefest

왜 그것을 선형으로 펼칠 수 없는지 이해합니다. 내가 여기서 이해하지 못하는 것은 피타고라스 또는 죄 / 의사와의 관련성입니다. 아마도 다이어그램이 도움이 될 것입니다.
aioobe

피타고라스 내 실수 그것에 대해 잊고 있지만, 기능의 차 본질을 이해 희망하십시오의 정확한 (2 / R2) × r은 증거가 필요하고 나는 이것에 대한 증거와 함께 올 드릴 수 없습니다
cheesefest

0

그런 재미있는 문제.
축 원점으로부터의 거리가 증가함에 따라 선택되는 점의 확률에 대한 이론적 근거는 위에서 여러 번 설명되었다. 우리는 U [0,1]의 근본을 취함으로써 그것을 설명합니다. 다음은 Python 3의 양수 r에 대한 일반적인 솔루션입니다.

import numpy
import math
import matplotlib.pyplot as plt

def sq_point_in_circle(r):
    """
    Generate a random point in an r radius circle 
    centered around the start of the axis
    """

    t = 2*math.pi*numpy.random.uniform()
    R = (numpy.random.uniform(0,1) ** 0.5) * r

    return(R*math.cos(t), R*math.sin(t))

R = 200 # Radius
N = 1000 # Samples

points = numpy.array([sq_point_in_circle(R) for i in range(N)])
plt.scatter(points[:, 0], points[:,1])

여기에 이미지 설명을 입력하십시오


0

직감을 사용할 수도 있습니다.

원의 면적은 pi*r^2

에 대한 r=1

이것은 우리에게 영역을 제공 pi합니다. 원 안에 점을 f균일하게 분산시키는 일종의 기능이 있다고 가정 해 봅시다 N=10. 여기의 비율은10 / pi

이제 우리는 면적과 포인트 수를 두 배로 늘립니다.

에 대한 r=2N=20

이것은 면적을 제공 4pi하고 비율은 지금 20/4pi또는10/2pi 입니다. 이의 성장은 2 차적이고 N비늘은 선형 이기 때문에 반지름이 클수록 비율이 점점 작아집니다 .

이 문제를 해결하기 위해 우리는 말할 수 있습니다.

x = r^2
sqrt(x) = r

이처럼 극좌표로 벡터를 생성한다면

length = random_0_1();
angle = random_0_2pi();

더 많은 포인트가 중앙에 착륙합니다.

length = sqrt(random_0_1());
angle = random_0_2pi();

length 더 이상 균일하게 분포되지 않지만 벡터는 균일하게 분포됩니다.


-1

1) -1과 1 사이에서 임의의 X를 선택하십시오.

var X:Number = Math.random() * 2 - 1;

2) 원 수식을 사용하여 X와 반지름이 1 인 경우 Y의 최대 값과 최소값을 계산합니다.

var YMin:Number = -Math.sqrt(1 - X * X);
var YMax:Number = Math.sqrt(1 - X * X);

3) 극단 사이에서 임의의 Y를 선택하십시오.

var Y:Number = Math.random() * (YMax - YMin) + YMin;

4) 위치 및 반경 값을 최종 값에 통합하십시오.

var finalX:Number = X * radius + pos.x;
var finalY:Number = Y * radois + pos.y;

2
균일하지 않음-p ([-1, Y]) = p ([0, Y])를 고려할 때 [-1, 0]의 확률은 [0, 0]보다 훨씬 높으며 단 하나만 있음 [-1, Y]에 대한 선택과 [0, Y]에 대한 많은 선택.
Amadan 2016 년

이 솔루션은 원의 왼쪽과 오른쪽을 향한 점을 선호합니다. x가 0에 가까운 점은 잘 표현되지 않습니다. 균등 분포가 아닙니다.
Dawood ibn Kareem
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.