Как создать случайную точку внутри круга радиуса 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?
Мы используем трюк под названием выборка обратного преобразования
- Из PDF создайте накопительную функцию распределения (CDF)
- Отразите это вдоль y = x
- Примените полученную функцию к равномерному значению от 0 до 1.
Звучит сложно? Позвольте мне вставить цитату с небольшой боковой дорожкой, которая передает интуицию:
Предположим, мы хотим сгенерировать случайную точку со следующим распределением:
То есть
- 1/5 баллов равномерно между 1 и 2, и
- 4/5 баллов равномерно между 2 и 3.
CDF - это, как следует из названия, кумулятивная версия PDF. Интуитивно понятно: в то время как PDF ( x ) описывает количество случайных значений в точке x , CDF ( x ) описывает количество случайных значений меньше значения x .
В этом случае CDF будет выглядеть так:
Чтобы увидеть, как это полезно, представьте, что мы стреляем пулями слева направо на равномерно распределенных высотах. Когда пули попадают в линию, они падают на землю:
Посмотрите, как плотность пуль на земле соответствует нашему желаемому распределению! Мы почти там!
Проблема в том, что для этой функции ось y является выходной, а ось x является входной . Мы можем только «стрелять пулями прямо с земли»! Нам нужна обратная функция!
Вот почему мы отражаем все это; х становится у, а у становится х :
Мы называем это CDF -1 . Чтобы получить значения в соответствии с желаемым распределением, мы используем CDF -1 (random ()).
… Итак, вернемся к генерации случайных значений радиуса, где наш PDF равен 2 х .
Шаг 1: Создайте CDF: так
как мы работаем с реалами, CDF выражается как интеграл PDF.
CDF ( x ) = ∫ 2 x = x 2
Шаг 2: Зеркально отразите CDF вдоль y = x :
Математически это сводится к обмену x и y и решению для y :
CDF : y = x 2
Обмен: x = y 2
Решить: y = √ x
CDF -1 : y = √ x
Шаг 3: применить полученную функцию к равномерному значению от 0 до 1
CDF -1 (random ()) = √random ()
Что мы и собираемся извлечь :-)