Генераторы псевдослучайных чисел
Пакет spire.random
содержит генераторы случайных чисел, подходящие для множества различных задач,
а также функциональный интерфейс для создания равномерного распределения значений.
Генераторы псевдослучайных чисел
Трейт mutable.Generator
представляет собой стратегию PRNG.
Используя равномерно сгенерированные значения Int
или Long
,
он может генерировать случайные значения, массивы значений и т.д.
Определить генератор относительно легко.
По умолчанию генераторы не являются потокобезопасными.
Синхронизированный генератор можно создать из несинхронизированного с помощью метода sync
.
Генераторы можно копировать, а их начальные значения сохранять и восстанавливать.
Это позволяет пользователям создавать детерминированные потоки значений,
используя одно и то же начальное значение.
В общем, пользователям предпочтительнее создавать и использовать свои собственные генераторы,
а не полагаться на один генератор в нескольких потоках.
Хотя трейт mutable.Generator
предоставляет только низкоуровневые методы, такие как nextInt
,
он может создавать значения любого типа, используя класс типов Dist[A]
, который будет обсуждаться ниже.
Трейт immutable.Generator
похож на mutable.Generator
, хотя хранимое в нем состояние является неизменным.
Каждый раз, когда генерируется число, также возвращается новый генератор,
что позволяет использовать эти генераторы в чисто функциональном контексте.
Здесь также применимы те же примеры Dist[A]
, которые использовались бы с изменяемым генератором.
Создание случайных значений с помощью Dist[A]
Класс типов Dist[A]
представляет собой стратегию генерации распределения значений A
для данного экземпляра Generator
.
Dist[A]
не дает никаких гарантий относительно того, как распределяются значения A
(например, он всегда может возвращать одно и то же значение).
Пользователи, интересующиеся конкретными реализациями, должны использовать трейты
Uniform[A]
, Gaussian[A]
и Exponential[A]
для создания экземпляров Dist[A]
, соответствующих их потребностям.
Сами объекты Dist[A]
неизменяемы и создаются от генераторов (как изменяемых, так и неизменяемых).
Их можно преобразовать с помощью map
, flatMap
и других комбинаторов.
При наличии соответствующей структуры A
с экземплярами Dist[A]
также можно работать, как если бы они были значениями.
Распределения
В настоящее время spire.random
предоставляет классы типов Uniform[A]
, Gaussian[A]
и Exponential[A]
,
которые с учетом соответствующих параметров могут создавать экземпляры Dist[A]
.
Поскольку большинство типов имеют (приблизительно) бесконечное число возможных значений,
на эти типы необходимо наложить границы и другие ограничения,
прежде чем мы сможем с пользой говорить о (или реализовывать) распределения вероятностей в Spire.
- Учитывая
min
иmax
, экземплярUniform[A]
может создать равномерно распределенный экземплярDist[A]
. - Учитывая
mean
иstdDev
, экземплярGaussian[A]
может создатьDist[A]
, значения которого распределяются в соответствии с желаемым распределением Гаусса. - Учитывая
rate
, экземплярGaussian[A]
может создатьDist[A]
, значения которого распределяются в соответствии с желаемым экспоненциальным распределением.
Например:
object DistDemo:
import spire.math.Complex
import spire.random.Dist
import spire.std.double.DoubleAlgebra
val rng = spire.random.rng.Cmwc5()
rng.nextLong()
// генерирует ассоциативный массив с от 10 до 20 записей
given Dist[Map[Int, Complex[Double]]] =
Dist.map[Int, Complex[Double]](10, 20)
val m = rng.next[Map[Int, Complex[Double]]]
// генерирует double в интервале [0.0, 1.0)
val n = rng.next[Double]
// генерирует комплексное число с действительной и мнимой частями в интервале [0.0, 1.0)
val q = rng.next[Complex[Double]]
Предоставляется множество экземпляров по умолчанию, и для пользовательских типов легко создавать собственные экземпляры.
Ссылки: