В настоящее время я участвую в создании системы частиц для нашей игры и разрабатываю некоторые формы эмиттеров.
Мое равномерное случайное распределение вдоль линии или вдоль прямоугольной области работает нормально - нет проблем.
Но теперь я хотел бы иметь что-то вроде одномерного градиента в этом распределении. Это будет означать, например, более низкие значения являются более распространенными, чем более высокие значения.
Я не знаю, какие уместные математические термины для этой проблемы, поэтому мои навыки поиска довольно бесполезны с этим. Мне нужно что-то простое в вычислительном отношении, поскольку система частиц должна быть эффективной.
mathematics
random
distribution
didito
источник
источник
Ответы:
Посмотрите на эту картинку:
Он показывает процесс отображения (случайного) значения на кривую. Предположим, вы генерируете равномерно распределенное случайное значение X в диапазоне от 0 до 1. Посредством сопоставления этого значения с кривой - или, другими словами, используя f (X) вместо X - вы можете искажать свое распределение любым удобным вам способом. ,
На этом рисунке первая кривая делает более высокие значения более вероятными; второе делает более низкие значения более вероятными; и третий делает кластер ценностей в середине. Точная формула кривой не очень важна и может быть выбрана, как вам нравится.
Например, первая кривая выглядит как квадратный корень, а вторая - как квадрат. Третий немного похож на куб, только переведенный. Если вы считаете, что квадратный корень слишком медленный, первая кривая также выглядит как f (X) = 1- (1-X) ^ 2 - инверсия квадрата. Или гипербола: f (X) = 2X / (1 + X).
Как показывает четвертая кривая, вы можете просто использовать предварительно вычисленную таблицу поиска. Это выглядит некрасиво, как кривая, но, вероятно, будет достаточно для системы частиц.
Эта общая техника очень проста и эффективна. Какое бы распределение вам ни понадобилось, просто представьте себе кривое отображение, и вы быстро разработаете формулу. Или, если у вашего движка есть редактор, просто создайте визуальный редактор для кривой!
источник
Более длинное объяснение:
Если у вас есть желаемое распределение вероятностей, такое как запрашиваемый градиент @didito, вы можете описать его как функцию. Допустим, вы хотите треугольное распределение, где вероятность в 0 равна 0.0, и вы хотите выбрать случайное число от 0 до 1. Мы можем записать его как y = x.
Следующим шагом является вычисление интеграла этой функции. В этом случае это . Оценивается от 0 до 1, это ½. Это имеет смысл - это треугольник с основанием 1 и высотой 1, поэтому его площадь равна ½.∫х = 1Икс2
Затем вы выбираете случайную точку равномерно от 0 до области (½ в нашем примере). Давайте назовем это z. (Мы выбираем равномерно из совокупного распределения .)
Следующий шаг - вернуться назад, чтобы найти, какое значение x (назовем его x̂) соответствует области z. Мы ищем , оцененный от 0 до x̂, равный z. Когда вы решите для , вы получите .∫х = 1Икс2 1х 2= z х = 2 з--√
В этом примере вы выбираете z от 0 до ½, а затем требуемое случайное число равно . Упрощенно, вы можете написать это как - именно то, что рекомендовал электронный бизнес.2 з--√ р а н д( 0 , 1 )--------√
источник
sqrt(random())
всю свою жизнь, но я пришел к этому эмпирически. Попытка привязать случайное число к кривой, и это сработало. Теперь, когда я немного разбираюсь в математике, очень важно знать, почему это работает!Вы, вероятно, получите близкое приближение к тому, что вы хотите, используя экспоненциальную систему.
Сделайте x основанным на чем-то вроде 1- (значение rnd ^) (при условии, что значение rnd находится в диапазоне от 0 до 1), и вы получите несколько различных вариантов поведения перекоса слева направо в зависимости от того, что вы используете. Более высокое значение даст вам более искаженное распределение
Вы можете использовать онлайн-инструмент для построения графиков, чтобы получить некоторые приблизительные представления о поведении, которое вам дадут различные уравнения, прежде чем помещать их, или вы можете просто поиграть с уравнениями непосредственно в вашей системе частиц, в зависимости от того, какой стиль вам больше по вкусу.
РЕДАКТИРОВАТЬ
Для чего-то вроде системы частиц, где время ЦП на частицу очень важно, использование Math.Pow (или языкового эквивалента) напрямую может привести к снижению производительности. Если требуется больше производительности и значение не изменяется во время выполнения, рассмотрите возможность переключения на эквивалентную функцию, такую как x * x вместо x ^ 2.
(Дробные показатели могут быть более серьезной проблемой, но кто-то с более сильным математическим фоном, чем я, вероятно, мог бы придумать хороший способ создать функцию приближения)
источник
value
, это бета (значение, 1).Вы ищете
Weighted Random Numbers
искомый термин: большинство алгоритмов, которые я видел, используют функции триггера, но я думаю, что я нашел способ, который будет эффективен:Создайте таблицу / массив / список (что угодно), который содержит значение множителя для случайной функции. Заполните это вручную или программно ...
... затем умножьте
random
на случайно выбранныйrandMulti
и, наконец, на максимальное значение распределения ...Я действительно считаю, что это будет намного быстрее, чем использование
sqrt
или другие более сложные в вычислительном отношении функции, и позволит использовать более персонализированные шаблоны группировки.источник
Я думаю, что вы просите распределение, полученное с помощью функции квадратного корня.
Это даст распределение в одномерном поле,
[0, 1]
где вероятность позиции эквивалентна этой позиции, то есть «треугольное распределение».Альтернативное поколение без корней:
Квадратный корень в оптимальной реализации - это всего лишь несколько команд умножения и суммирования без ветвей. (См .: http://en.wikipedia.org/wiki/Fast_inverse_square_root ). Какая из этих двух функций быстрее, зависит от платформы и случайного генератора. Например, на платформе x86 потребуется всего несколько непредсказуемых ветвей в генераторе случайных чисел, чтобы замедлить второй метод.
источник
Просто используйте бета-дистрибутив:
и т.п.
Два параметра формы не обязательно должны быть целыми числами.
источник
uniform_generator()
звонок наgsl_ran_beta(rng, a, b)
. Смотрите здесь: gnu.org/software/gsl/manual/html_node/…Еще проще, в зависимости от скорости вашего генератора случайных чисел, вы можете просто сгенерировать два значения и усреднить их.
Или, еще проще, где X является результатом ГСЧ, во- первых
double y = double(1/x);
,x = y*[maximum return value of rng];
. Это будет взвешивать числа в геометрической прогрессии до более низких чисел.Создайте и усредните большее количество значений, чтобы увеличить вероятность приближения значений к центру.
Конечно, это работает только для стандартных распределений кривых колокольчиков или их «свернутых» версий *, но с быстрым генератором это может быть быстрее и проще, чем использование различных математических функций, таких как sqrt.
Вы можете найти все виды исследований по этому вопросу для кривых колокольчиков. На самом деле, Anydice.com является хорошим сайтом, который генерирует графики для различных методов бросания костей. Хотя вы используете ГСЧ, предпосылка такая же, как и результаты. Так что это хорошее место для просмотра дистрибутива еще до того, как его кодировать
* Кроме того, вы можете «сложить» распределение результатов по оси, взяв ось и вычтя усредненный результат, а затем добавив ось. Например, вы хотите, чтобы более низкие значения были более распространенными, и допустим, что вы хотите, чтобы 15 было вашим минимальным значением, а 35 - вашим максимальным значением, диапазон 20. Таким образом, вы генерируете и усредняете вместе два значения с диапазоном 20 ( в два раза больше желаемого диапазона), что даст колокольчик с центром в 20 (мы вычитаем пять в конце, чтобы сместить диапазон с 20 до 40, с 15 до 35). Возьмите сгенерированные числа X и Y.
Финальный номер,
Если ноль - ваш минимум, даже лучше, сделайте это вместо этого,
источник