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):

Как выбрать одно из четырех значений с желаемым распределением? Мы можем сложить их, выбрать равномерно случайное значение между 0 и 1 по оси Y и выбрать сегмент в этой точке:

Хотя есть и другой способ визуализации этого выбора. Вместо этого мы могли бы заменить каждое значение распределения на накопление значений до этого момента:

А теперь мы рассматриваем верхнюю строку этой диаграммы как функцию f(x) = yи инвертируем ее, чтобы получить функцию , которую мы можем применить к равномерно случайному значению в :g(y) = f-1(y) = xy ∈ [0,1]

Круто, так как можно использовать это для генерации линейного распределения радиусов? Это дистрибутив, который мы хотим:

Первым шагом является накопление значений распределения. Но распределение непрерывно, поэтому вместо суммирования по всем предыдущим значениям мы берем интеграл от 0до r. Мы можем легко решить это аналитически . Тем не менее, мы хотим, чтобы это было нормализовано, то есть умножило это на константу так, чтобы это дало максимальное значение , так что мы действительно хотим :∫0r r dr = 1/2 r21rr2

И, наконец, мы инвертируем это, чтобы получить функцию, к которой мы можем применить единообразное значение [0,1], что мы снова можем сделать аналитически: просто r = √y, где yслучайное значение:

Это довольно полезный метод, который часто можно использовать для точной генерации простых дистрибутивов (он работает для любого дистрибутива, но для сложных двух последних шагов, возможно, придется решать численно). Однако я бы не стал использовать его в данном конкретном случае в производственном коде, потому что квадратный корень, синус и косинус чрезмерно дороги: использование алгоритма на основе отклонения в среднем намного быстрее, потому что оно требует только сложения и умножения.