Spec-Zone.ru › Nim

std/random

Исходный кодИзменить

Стандартный генератор псевдослучайных чисел (ГПСЧ) Nim.

Реализация основана на библиотеке xoroshiro128+ (xor/rotate/shift/rotate).

  • Подробнее: http://xoroshiro.di.unimi.it
  • Реализация на C: http://xoroshiro.di.unimi.it/xoroshiro128plus.c

Не используйте этот модуль для криптографических целей!

Основное использование

Пример:

import std/random
# Call randomize() once to initialize the default random number generator.
# If this is not called, the same results will occur every time these
# examples are run.
randomize()

# Pick a number in 0..100.
let num = rand(100)
doAssert num in 0..100

# Roll a six-sided die.
let roll = rand(1..6)
doAssert roll in 1..6

# Pick a marble from a bag.
let marbles = ["red", "blue", "green", "yellow", "purple"]
let pick = sample(marbles)
doAssert pick in marbles

# Shuffle some cards.
var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
shuffle(cards)
doAssert cards.len == 5

Все эти примеры используют по умолчанию ГПСЧ. Тип Rand представляет состояние ГПСЧ. Для удобства этот модуль содержит состояние Rand по умолчанию, соответствующее состоянию по умолчанию ГПСЧ. Большинство процедур в этом модуле, которые не принимают параметр Rand, включая те, которые вызываются в приведенных выше примерах, используют генератор по умолчанию. Эти процедуры не потокобезопасны.

Обратите внимание, что генератор по умолчанию всегда начинается в одном и том же состоянии. Процедуру randomize можно вызвать для инициализации генератора по умолчанию с начальным значением, основанным на текущем времени, и её нужно вызывать только один раз перед первым использованием процедур из этого модуля. Если randomize не вызывается, генератор по умолчанию всегда будет давать одинаковые результаты.

ГПСЧ, независимые от генератора по умолчанию, можно создать с помощью процедуры initRand.

Ещё раз подчеркнём, что этот модуль не должен использоваться для криптографических приложений.

См. также

  • Модуль std/sysrand для криптографически безопасного генератора псевдослучайных чисел
  • Модуль math для основных математических функций
  • Модуль stats для статистического анализа
  • Список криптографических и хеширующих модулей в стандартной библиотеке

Импорты

algorithm, math, since, jsutils, hashes, os, sysrand, monotimes, locks

Типы

Rand = object

Состояние генератора псевдослучайных чисел.

Создайте новое состояние Rand с помощью процедуры initRand.

Модуль содержит состояние Rand по умолчанию для удобства. Оно соответствует состоянию по умолчанию ГПСЧ. Состояние Rand по умолчанию всегда начинает с одних и тех же значений, но процедура randomize может быть использована для инициализации генератора по умолчанию значением, основанным на текущем времени.

Многие процедуры имеют две вариации: одна, принимающая параметр Rand, и другая, использующая генератор по умолчанию. Процедуры, использующие генератор по умолчанию, не потокобезопасны!

Исходный код Изменить

Процедуры

proc gauss(mu = 0.0; sigma = 1.0): float {....raises: [], tags: [], forbids: [].}

Возвращает случайную величину Гаусса со средним значением mu и стандартным отклонением sigma.

Если randomize не была вызвана, порядок результатов этой процедуры всегда будет одинаковым.

Эта процедура использует генератор по умолчанию. Таким образом, она не потокобезопасна.

Исходный код Изменить
proc gauss(r: var Rand; mu = 0.0; sigma = 1.0): float {....raises: [], tags: [],
    forbids: [].}
Возвращает случайную величину Гаусса со средним значением mu и стандартным отклонением sigma, используя заданное состояние. Исходный код Изменить
proc initRand(): Rand {....raises: [], tags: [], forbids: [].}

Инициализирует новое состояние Rand.

Результат независим от состояния генератора по умолчанию.

Примечание: Не работает для компиляционного виртуальной машины.

См. также:

  • Процедура initRand, которая принимает seed для нового состояния Rand
  • Процедура randomize для инициализации генератора по умолчанию с помощью текущего времени
  • Процедура randomize, которая принимает seed для генератора по умолчанию
Исходный код Изменить
proc initRand(seed: int64): Rand {....raises: [], tags: [], forbids: [].}

Инициализирует новое состояние Rand с заданным seed.

Предоставление определённого seed будет давать одни и те же результаты для этого seed каждый раз.

Полученное состояние независимо от состояния по умолчанию ГПСЧ. Когда seed == 0, мы внутренне устанавливаем seed в определенное реализацией ненулевое значение.

См. также:

  • Процедура initRand, которая использует текущее время
  • Процедура randomize, которая принимает seed для генератора по умолчанию
  • Процедура randomize, которая инициализирует генератор по умолчанию с помощью текущего времени

Пример:

from std/times import getTime, toUnix, nanosecond

var r1 = initRand(123)
let now = getTime()
var r2 = initRand(now.toUnix * 1_000_000_000 + now.nanosecond)
Исходный код Изменить
proc next(r: var Rand): uint64 {....raises: [], tags: [], forbids: [].}

Вычисляет случайное uint64 число, используя заданное состояние.

См. также:

  • Процедура rand, которая возвращает целое число между нулём и заданным верхним пределом
  • Процедура rand, которая возвращает число с плавающей точкой
  • Процедура rand, которая принимает срез
  • Процедура rand, которая принимает тип целого числа или диапазона
  • Процедура skipRandomNumbers

Пример: cmd: -r:off

var r = initRand(2019)
assert r.next() == 13223559681708962501'u64 # implementation defined
assert r.next() == 7229677234260823147'u64 # ditto
Исходный код Изменить
proc rand(max: float): float {....gcsafe, raises: [], tags: [], forbids: [].}

Возвращает случайное число с плавающей точкой в диапазоне 0.0..max.

Если randomize не был вызван, последовательность случайных чисел, возвращаемых этим методом, всегда будет одинаковой.

Этот метод использует по умолчанию генератор случайных чисел (RNG). Поэтому он не потокобезопасен.

См. также:

  • метод rand, возвращающий число с плавающей точкой, используя предоставленное состояние
  • метод rand, возвращающий целое число
  • метод rand, принимающий срез
  • метод rand, принимающий тип целого числа или диапазона

Пример:

randomize(234)
let f = rand(1.0) # 8.717181376738381e-07
Исходный код Изменить
proc rand(max: int): int {....gcsafe, raises: [], tags: [], forbids: [].}

Возвращает случайное целое число в диапазоне 0..max.

Если randomize не был вызван, последовательность случайных чисел, возвращаемых этим методом, всегда будет одинаковой.

Этот метод использует по умолчанию генератор случайных чисел (RNG). Поэтому он не потокобезопасен.

См. также:

  • метод rand, возвращающий целое число, используя предоставленное состояние
  • метод rand, возвращающий число с плавающей точкой
  • метод rand, принимающий срез
  • метод rand, принимающий тип целого числа или диапазона

Пример: cmd: -r:off

randomize(123)
assert [rand(100), rand(100)] == [96, 63] # implementation defined
Исходный код Изменить
proc rand(r: var Rand; max: Natural): int {....gcsafe, raises: [], tags: [],
    forbids: [].}

Возвращает случайное целое число в диапазоне 0..max используя заданное состояние.

См. также:

  • метод rand, возвращающий целое число, используя генератор случайных чисел по умолчанию
  • метод rand, возвращающий число с плавающей точкой
  • метод rand, принимающий срез
  • метод rand, принимающий тип целого числа или диапазона

Пример:

var r = initRand(123)
if false:
  assert r.rand(100) == 96 # implementation defined
Исходный код Изменить
proc rand(r: var Rand; max: range[0.0 .. high(float)]): float {....gcsafe,
    raises: [], tags: [], forbids: [].}

Возвращает случайное число с плавающей точкой в диапазоне 0.0..max используя заданное состояние.

См. также:

  • метод rand, возвращающий число с плавающей точкой, используя генератор случайных чисел по умолчанию
  • метод rand, возвращающий целое число
  • метод rand, принимающий срез
  • метод rand, принимающий тип целого числа или диапазона

Пример:

var r = initRand(234)
let f = r.rand(1.0) # 8.717181376738381e-07
Исходный код Изменить
proc rand[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T

Для среза a..b, возвращает значение в диапазоне a..b используя заданное состояние.

Допустимые типы для T — целые числа, числа с плавающей точкой и перечисления без пробелов.

См. также:

  • метод rand, принимающий срез и использующий генератор случайных чисел по умолчанию
  • метод rand, возвращающий целое число
  • метод rand, возвращающий число с плавающей точкой
  • метод rand, принимающий тип целого числа или диапазона

Пример:

var r = initRand(345)
assert r.rand(1..5) <= 5
assert r.rand(-1.1 .. 1.2) >= -1.1
Исходный код Изменить
proc rand[T: Ordinal or SomeFloat](x: HSlice[T, T]): T

Для среза a..b, возвращает значение в диапазоне a..b.

Допустимые типы для T — целые числа, числа с плавающей точкой и перечисления без пробелов.

Если randomize не был вызван, последовательность случайных чисел, возвращаемых этим методом, всегда будет одинаковой.

Этот метод использует по умолчанию генератор случайных чисел (RNG). Поэтому он не потокобезопасен.

См. также:

  • метод rand, принимающий срез и использующий предоставленное состояние
  • метод rand, возвращающий целое число
  • метод rand, возвращающий число с плавающей точкой
  • метод rand, принимающий тип целого числа или диапазона

Пример:

randomize(345)
assert rand(1..6) <= 6
Исходный код Изменить
proc rand[T: Ordinal](r: var Rand; t: typedesc[T]): T

Возвращает случайный тип Ordinal в диапазоне low(T)..high(T).

Если randomize не был вызван, последовательность случайных чисел, возвращаемых этим методом, всегда будет одинаковой.

См. также:

  • метод rand, возвращающий целое число
  • метод rand, возвращающий число с плавающей точкой
  • метод rand, принимающий срез
Исходный код Изменить
proc rand[T: Ordinal](t: typedesc[T]): T

Возвращает случайный тип Ordinal в диапазоне low(T)..high(T).

Если randomize не был вызван, последовательность случайных чисел, возвращаемых этим методом, всегда будет одинаковой.

Этот метод использует по умолчанию генератор случайных чисел (RNG). Поэтому он не потокобезопасен.

См. также:

  • метод rand, возвращающий целое число
  • метод rand, возвращающий число с плавающей точкой
  • метод rand, принимающий срез

Пример:

randomize(567)
type E = enum a, b, c, d

assert rand(E) in a..d
assert rand(char) in low(char)..high(char)
assert rand(int8) in low(int8)..high(int8)
assert rand(uint32) in low(uint32)..high(uint32)
assert rand(range[1..16]) in 1..16
Исходный код Изменить
proc randomize() {....gcsafe, raises: [], tags: [], forbids: [].}

Инициализирует генератор случайных чисел по умолчанию с помощью зерна, полученного из источника случайных чисел.

Этот метод нужно вызвать только один раз, и его следует вызвать перед первым использованием методов из этого модуля, использующих генератор случайных чисел по умолчанию.

Примечание: Не работает для компиляционной виртуальной машины.

См. также:

  • метод randomize, принимающий зерно
  • метод initRand, инициализирующий состояние Rand с помощью текущего времени
  • метод initRand, инициализирующий состояние Rand заданным зерном
Исходный код Изменить
proc randomize(seed: int64) {....gcsafe, raises: [], tags: [], forbids: [].}

Инициализирует генератор случайных чисел по умолчанию с заданным зерном.

Предоставление определенного зерна приведет к одинаковым результатам для этого зерна каждый раз.

См. также:

  • метод initRand, инициализирующий состояние Rand заданным зерном
  • метод randomize, использующий вместо этого текущее время
  • метод initRand, инициализирующий состояние Rand с помощью текущего времени

Пример:

from std/times import getTime, toUnix, nanosecond

randomize(123)

let now = getTime()
randomize(now.toUnix * 1_000_000_000 + now.nanosecond)
Исходный код Изменить
proc sample[T, U](a: openArray[T]; cdf: openArray[U]): T

Возвращает элемент из a с использованием кумулятивной функции распределения (CDF).

Этот метод работает аналогично sample. Подробности см. в документации этого метода.

Если randomize не был вызван, порядок результатов этого метода всегда будет одинаковым.

Этот метод использует стандартный генератор случайных чисел. Поэтому он не потокобезопасен.

См. также:

  • метод sample, который также использует CDF, но использует предоставленное состояние
  • метод sample, который не использует CDF
  • метод sample для множеств

Пример:

from std/math import cumsummed

let marbles = ["red", "blue", "green", "yellow", "purple"]
let count = [1, 6, 8, 3, 4]
let cdf = count.cumsummed
randomize(789)
assert sample(marbles, cdf) in marbles
Исходный код Редактировать
proc sample[T, U](r: var Rand; a: openArray[T]; cdf: openArray[U]): T

Возвращает элемент из a с использованием кумулятивной функции распределения (CDF) и заданного состояния.

Аргумент cdf не обязательно должен быть нормированным и может содержать любые типы элементов, которые можно преобразовать в float. Его длина должна быть такой же, как у a. Каждый элемент в cdf должен быть больше или равен предыдущему.

В качестве аргумента cdf можно использовать результат вызова метода cumsum и значение, возвращаемое методом cumsummed (оба находятся в модуле math).

См. также:

  • метод sample, который также использует CDF, но использует стандартный генератор случайных чисел
  • метод sample, который не использует CDF
  • метод sample для множеств

Пример:

from std/math import cumsummed

let marbles = ["red", "blue", "green", "yellow", "purple"]
let count = [1, 6, 8, 3, 4]
let cdf = count.cumsummed
var r = initRand(789)
assert r.sample(marbles, cdf) in marbles
Исходный код Редактировать
proc sample[T](a: openArray[T]): lent T

Возвращает случайный элемент из a.

Если randomize не был вызван, порядок результатов этого метода всегда будет одинаковым.

Этот метод использует стандартный генератор случайных чисел. Поэтому он не потокобезопасен.

См. также:

  • метод sample, который использует предоставленное состояние
  • метод sample, который использует кумулятивную функцию распределения
  • метод sample для множеств

Пример:

let marbles = ["red", "blue", "green", "yellow", "purple"]
randomize(456)
assert sample(marbles) in marbles
Исходный код Редактировать
proc sample[T](r: var Rand; a: openArray[T]): T

Возвращает случайный элемент из a с использованием заданного состояния.

См. также:

  • метод sample, который использует стандартный генератор случайных чисел
  • метод sample, который использует кумулятивную функцию распределения
  • метод sample для множеств

Пример:

let marbles = ["red", "blue", "green", "yellow", "purple"]
var r = initRand(456)
assert r.sample(marbles) in marbles
Исходный код Редактировать
proc sample[T](r: var Rand; s: set[T]): T

Возвращает случайный элемент из множества s с использованием заданного состояния.

См. также:

  • метод sample, который использует стандартный генератор случайных чисел
  • метод sample для openArray
  • метод sample, который использует кумулятивную функцию распределения

Пример:

var r = initRand(987)
let s = {1, 3, 5, 7, 9}
assert r.sample(s) in s
Исходный код Редактировать
proc sample[T](s: set[T]): T

Возвращает случайный элемент из множества s.

Если randomize не был вызван, порядок результатов этого метода всегда будет одинаковым.

Этот метод использует стандартный генератор случайных чисел. Поэтому он не потокобезопасен.

См. также:

  • метод sample, который использует предоставленное состояние
  • метод sample для openArray
  • метод sample, который использует кумулятивную функцию распределения

Пример:

randomize(987)
let s = {1, 3, 5, 7, 9}
assert sample(s) in s
Исходный код Редактировать
proc shuffle[T](r: var Rand; x: var openArray[T])

Перемешивает последовательность элементов на месте, используя заданное состояние.

См. также:

  • метод shuffle, который использует стандартный генератор случайных чисел

Пример:

var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
var r = initRand(678)
r.shuffle(cards)
import std/algorithm
assert cards.sorted == @["Ace", "Jack", "King", "Queen", "Ten"]
Исходный код Редактировать
proc shuffle[T](x: var openArray[T])

Перемешивает последовательность элементов на месте.

Если randomize не был вызван, порядок результатов этого метода всегда будет одинаковым.

Этот метод использует стандартный генератор случайных чисел. Поэтому он не потокобезопасен.

См. также:

  • метод shuffle, который использует предоставленное состояние

Пример:

var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
randomize(678)
shuffle(cards)
import std/algorithm
assert cards.sorted == @["Ace", "Jack", "King", "Queen", "Ten"]
Исходный код Редактировать
proc skipRandomNumbers(s: var Rand) {....raises: [], tags: [], forbids: [].}

Функция перехода для генератора.

Этот метод эквивалентен 2^64 вызовам next и может использоваться для генерации 2^64 непересекающихся подпоследовательностей для параллельных вычислений.

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

Если много потоков будут генерировать случайные числа одновременно, лучше создать одно состояние Rand и передать его каждому потоку. После передачи состояния Rand потоку, вызовите этот метод перед передачей его следующему. Используя состояние Rand таким образом, подпоследовательности случайных чисел, генерируемых в каждом потоке, никогда не будут перекрываться, пока ни один поток не сгенерирует более 2^64 случайных чисел.

См. также:

  • метод next

Пример: cmd: --threads:on

import std/random

const numbers = 100000

var
  thr: array[0..3, Thread[(Rand, int)]]
  vals: array[0..3, int]

proc randomSum(params: tuple[r: Rand, index: int]) {.thread.} =
  var r = params.r
  var s = 0 # avoid cache thrashing
  for i in 1..numbers:
    s += r.rand(0..10)
  vals[params.index] = s

var r = initRand(2019)
for i in 0..<thr.len:
  createThread(thr[i], randomSum, (r, i))
  r.skipRandomNumbers()

joinThreads(thr)

for val in vals:
  doAssert abs(val - numbers * 5) / numbers < 0.1

doAssert vals == [501737, 497901, 500683, 500157]
Исходный код Редактировать

Шаблоны

template randState(): untyped
Делает стандартное состояние Rand доступным из других модулей. Полезно для авторов модулей. Исходный код Редактировать

© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/random.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API