CJam, 28 27 바이트
PP+mr_mc\ms]1.mrmqf*"(,)".\
이 솔루션은 거부 기반이 아닙니다. 점을 극좌표로 생성하지만 점의 균일 한 밀도를 달성하기 위해 반지름의 균일하지 않은 분포를 사용합니다.
여기에서 테스트하십시오.
설명
PP+ e# Push 2π.
mr_ e# Get a random float between 0 and 2π, make a copy.
mc\ e# Take the cosine of one copy and swap with the other.
ms] e# Take the sine of the other copy and wrap them in an array.
e# This gives us a uniform point on the unit circle.
1.mr e# Get a random float between 0 and 1.
mq e# Take the square root. This is the random radius.
f* e# Multiply x and y by this radius.
"(,)".\ e# Put the resulting numbers in the required format.
왜 작동합니까? 반지름이 좁은 고리 r
와 너비가 작은 것을 고려하십시오 dr
. 면적은 대략 2π*r*dr
(환형이 좁 으면 내주와 외주가 거의 같고, 곡률을 무시할 수있어 면적이 원주와 옆면의 가로 길이를 가진 직사각형의 영역으로 취급 될 수 있음) 고리). 따라서 면적은 반지름에 따라 선형으로 증가합니다. 즉, 일정한 밀도를 달성하기 위해 (반지름의 두 배에서 채우는 면적이 두 배이므로, 두 배의 포인트가 필요합니다) 랜덤 반경의 선형 분포가 필요합니다.
0에서 1까지 선형 랜덤 분포를 어떻게 생성합니까? 개별 사례를 먼저 살펴 보겠습니다. 예를 들어, 우리는 4 배의 원하는 분포를가집니다 {0.1, 0.4, 0.2, 0.3}
(즉, 우리는 1
4 배 0
, 두 배는 일반적이고 2
; 우리는 3
세배를 공통적으로 원합니다 0
) :
원하는 분포로 4 가지 값 중 하나를 어떻게 선택할 수 있습니까? 우리는 그것들을 쌓아 올릴 수 있고 y 축에서 0과 1 사이의 균일 한 무작위 값을 고르고 그 시점에서 세그먼트를 선택할 수 있습니다 :
이 선택을 시각화하는 다른 방법이 있습니다. 대신 분포의 각 값을 해당 시점까지의 값 누적으로 대체 할 수 있습니다.
이제이 차트의 맨 윗줄을 함수로 취급하고 함수 f(x) = y
를 얻기 위해 뒤집습니다.이 함수 는 다음 에서 균일하게 임의의 값을 적용 할 수 있습니다 .g(y) = f-1(y) = x
y ∈ [0,1]
근사한데, 어떻게 이것을 사용하여 반지름의 선형 분포를 생성 할 수 있습니까? 이것은 우리가 원하는 분포입니다.
첫 번째 단계는 분포 값을 누적하는 것입니다. 그러나 분포는 연속적이므로 이전의 모든 값을 합산하는 대신에서 0
를 적분 합니다 r
. 이를 분석적으로 쉽게 해결할 수 있습니다 . 그러나 우리는 이것을 정규화하기를 원합니다. 즉 , 최대 값을 얻을 수 있도록 상수를 곱하면 실제로 원하는 것은 다음과 같습니다.∫0r r dr = 1/2 r2
1
r
r2
그리고 마지막으로, 우리는이 반전은 우리가 균일 한 값에 적용 할 수있는 기능을 얻을 수 [0,1]
는 단지 : 우리는 다시 해석 할 수있는, r = √y
, y
임의의 값입니다 :
이것은 간단한 분포를 정확하게 생성하기 위해 종종 사용될 수있는 상당히 유용한 기술입니다 (모든 분포에서 작동하지만 복잡한 것에서는 마지막 두 단계를 수치 적으로 해결해야 할 수도 있습니다). 그러나 제곱근, 사인 및 코사인이 엄청나게 비싸기 때문에 생산 코드 에서이 특별한 경우에는 사용하지 않을 것입니다. 거부 기반 알고리즘을 사용하는 것은 평균과 곱셈 만 필요하기 때문에 평균적으로 훨씬 빠릅니다.