# random

- Manual
- Standard library
- Index

Search:
Group by:

Nim's standard random number generator.

Its implementation is based on the `xoroshiro128+` (xor/rotate/shift/rotate) library.

- More information: http://xoroshiro.di.unimi.it/
- C implementation: http://xoroshiro.di.unimi.it/xoroshiro128plus.c

Do not use this module for cryptographic purposes!

# Basic usage

To get started, here are some examples:

    import 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 between 0 and 100
    let num = rand(100)
    echo num

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

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

    # Shuffle some cards
    var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
    shuffle(cards)
    echo cards

These examples all use the default random number generator. The Rand type represents the state of a random number generator. For convenience, this module contains a default Rand state that corresponds to the default random number generator. Most procs in this module which do not take in a Rand parameter, including those called in the above examples, use the default generator. Those procs are not thread-safe.

Note that the default generator always starts in the same state. The randomize proc can be called to initialize the default generator with a seed based on the current time, and it only needs to be called once before the first usage of procs from this module. If `randomize` is not called, then the default generator will always produce the same results.

Generators that are independent of the default one can be created with the initRand proc.

Again, it is important to remember that this module must not be used for cryptographic applications.

# See also

- math module for basic math routines
- mersenne module for the Mersenne Twister random number generator
- stats module for statistical analysis
- list of cryptographic and hashing modules in the standard library

# Imports

algorithm, times

# Types

    Rand = object
      a0, a1: Ui

  State of a random number generator.

  Create a new Rand state using the initRand proc.

  The module contains a default Rand state for convenience. It corresponds to the default random number generator's state. The default Rand state always starts with the same values, but the randomize proc can be used to seed the default generator with a value based on the current time.

  Many procs have two variations: one that takes in a Rand parameter and another that uses the default generator. The procs that use the default generator are not thread-safe!

  Source Edit

# Procs

    proc next(r: var Rand): uint64 {...}{.raises: [], tags: [].}

  Computes a random `uint64` number using the given state.

  See also:

  - rand proc that returns an integer between zero and a given upper bound
  - rand proc that returns a float
  - rand proc that accepts a slice
  - rand proc that accepts an integer or range type
  - skipRandomNumbers proc

  Examples:

      var r = initRand(2019)
      doAssert r.next() == 138744656611299'u64
      doAssert r.next() == 979810537855049344'u64
      doAssert r.next() == 3628232584225300704'u64

  Source Edit

    proc skipRandomNumbers(s: var Rand) {...}{.raises: [], tags: [].}

  The jump function for the generator.

  This proc is equivalent to 2^64 calls to next, and it can be used to generate 2^64 non-overlapping subsequences for parallel computations.

  When multiple threads are generating random numbers, each thread must own the Rand state it is using so that the thread can safely obtain random numbers. However, if each thread creates its own Rand state, the subsequences of random numbers that each thread generates may overlap, even if the provided seeds are unique. This is more likely to happen as the number of threads and amount of random numbers generated increases.

  If many threads will generate random numbers concurrently, it is better to create a single Rand state and pass it to each thread. After passing the Rand state to a thread, call this proc before passing it to the next one. By using the Rand state this way, the subsequences of random numbers generated in each thread will never overlap as long as no thread generates more than 2^64 random numbers.

  The following example below demonstrates this pattern:

      # Compile this example with --threads:on
      import random
      import threadpool

      const spawns = 4
      const numbers = 100000

      proc randomSum(rand: Rand): int =
        var r = rand
        for i in 1..numbers:
          result += rand(1..10)

      var r = initRand(2019)
      var vals: array[spawns, FlowVar[int]]
      for val in vals.mitems:
        val = spawn(randomSum(r))
        r.skipRandomNumbers()

      for val in vals:
        echo ^val

  See also:

  - next proc
  Source Edit

    proc random(max: int): int {...}{.gcsafe, locks: 0, deprecated: "Deprecated since v0.18.0; use \'rand\' instead",
                             raises: [], tags: [].}

  Deprecated: Deprecated since v0.18.0; use 'rand' instead
  Source Edit

    proc random(max: float): float {...}{.gcsafe, locks: 0, deprecated: "Deprecated since v0.18.0; use \'rand\' instead",
                                 raises: [], tags: [].}

  Deprecated: Deprecated since v0.18.0; use 'rand' instead
  Source Edit

    proc random[T](x: HSlice[T, T]): T {...}{.deprecated: "Deprecated since v0.18.0; use \'rand\' instead".}

  Deprecated: Deprecated since v0.18.0; use 'rand' instead
  Source Edit

    proc random[T](a: openArray[T]): T {...}{.deprecated: "Deprecated since v0.18.0; use \'sample\' instead".}

  Deprecated: Deprecated since v0.18.0; use 'sample' instead
  Source Edit

    proc rand(r: var Rand; max: Natural): int {...}{.gcsafe, locks: 0, raises: [], tags: [].}

  Returns a random integer in the range `0..max` using the given state.

  See also:

  - rand proc that returns an integer using the default random number generator
  - rand proc that returns a float
  - rand proc that accepts a slice
  - rand proc that accepts an integer or range type

  Examples:

      var r = initRand(123)
      doAssert r.rand(100) == 0
      doAssert r.rand(100) == 96
      doAssert r.rand(100) == 66

  Source Edit

    proc rand(max: int): int {...}{.gcsafe, locks: 0, raises: [], tags: [].}

  Returns a random integer in the range `0..max`.

  If randomize has not been called, the sequence of random numbers returned from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - rand proc that returns an integer using a provided state
  - rand proc that returns a float
  - rand proc that accepts a slice
  - rand proc that accepts an integer or range type

  Examples:

      randomize(123)
      doAssert rand(100) == 0
      doAssert rand(100) == 96
      doAssert rand(100) == 66

  Source Edit

    proc rand(r: var Rand; max: range[0.0 .. high(float)]): float {...}{.gcsafe, locks: 0,
        raises: [], tags: [].}

  Returns a random floating point number in the range `0.0..max` using the given state.

  See also:

  - rand proc that returns a float using the default random number generator
  - rand proc that returns an integer
  - rand proc that accepts a slice
  - rand proc that accepts an integer or range type

  Examples:

      var r = initRand(234)
      let f = r.rand(1.0)
      ## f = 8.717181376738381e-07

  Source Edit

    proc rand(max: float): float {...}{.gcsafe, locks: 0, raises: [], tags: [].}

  Returns a random floating point number in the range `0.0..max`.

  If randomize has not been called, the sequence of random numbers returned from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - rand proc that returns a float using a provided state
  - rand proc that returns an integer
  - rand proc that accepts a slice
  - rand proc that accepts an integer or range type

  Examples:

      randomize(234)
      let f = rand(1.0)
      ## f = 8.717181376738381e-07

  Source Edit

    proc rand[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T

  For a slice `a..b`, returns a value in the range `a..b` using the given state.

  Allowed types for `T` are integers, floats, and enums without holes.

  See also:

  - rand proc that accepts a slice and uses the default random number generator
  - rand proc that returns an integer
  - rand proc that returns a float
  - rand proc that accepts an integer or range type

  Examples:

      var r = initRand(345)
      doAssert r.rand(1 .. 6) == 4
      doAssert r.rand(1 .. 6) == 4
      doAssert r.rand(1 .. 6) == 6
      let f = r.rand(-1.0 .. 1.0)
      ## f = 0.8741183448756229

  Source Edit

    proc rand[T: Ordinal or SomeFloat](x: HSlice[T, T]): T

  For a slice `a..b`, returns a value in the range `a..b`.

  Allowed types for `T` are integers, floats, and enums without holes.

  If randomize has not been called, the sequence of random numbers returned from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - rand proc that accepts a slice and uses a provided state
  - rand proc that returns an integer
  - rand proc that returns a floating point number
  - rand proc that accepts an integer or range type

  Examples:

      randomize(345)
      doAssert rand(1 .. 6) == 4
      doAssert rand(1 .. 6) == 4
      doAssert rand(1 .. 6) == 6

  Source Edit

    proc rand[T](r: var Rand; a: openArray[T]): T {...}{.
        deprecated: "Deprecated since v0.20.0; use \'sample\' instead".}

  Deprecated: Deprecated since v0.20.0; use 'sample' instead
  Source Edit

    proc rand[T: SomeInteger](t: typedesc[T]): T

  Returns a random integer in the range `low(T)..high(T)`.

  If randomize has not been called, the sequence of random numbers returned from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - rand proc that returns an integer
  - rand proc that returns a floating point number
  - rand proc that accepts a slice

  Examples:

      randomize(567)
      doAssert rand(int8) == 55
      doAssert rand(int8) == -42
      doAssert rand(int8) == 43
      doAssert rand(uint32) == 578980729'u32
      doAssert rand(uint32) == 4052940463'u32
      doAssert rand(uint32) == 2163872389'u32
      doAssert rand(range[1 .. 16]) == 11
      doAssert rand(range[1 .. 16]) == 4
      doAssert rand(range[1 .. 16]) == 16

  Source Edit

    proc rand[T](a: openArray[T]): T {...}{.deprecated: "Deprecated since v0.20.0; use \'sample\' instead".}

  Deprecated: Deprecated since v0.20.0; use 'sample' instead
  Source Edit

    proc sample[T](r: var Rand; s: set[T]): T

  Returns a random element from the set `s` using the given state.

  See also:

  - sample proc that uses the default random number generator
  - sample proc for openarrays
  - sample proc that uses a cumulative distribution function

  Examples:

      var r = initRand(987)
      let s = {1, 3, 5, 7, 9}
      doAssert r.sample(s) == 5
      doAssert r.sample(s) == 7
      doAssert r.sample(s) == 1

  Source Edit

    proc sample[T](s: set[T]): T

  Returns a random element from the set `s`.

  If randomize has not been called, the order of outcomes from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - sample proc that uses a provided state
  - sample proc for openarrays
  - sample proc that uses a cumulative distribution function

  Examples:

      randomize(987)
      let s = {1, 3, 5, 7, 9}
      doAssert sample(s) == 5
      doAssert sample(s) == 7
      doAssert sample(s) == 1

  Source Edit

    proc sample[T](r: var Rand; a: openArray[T]): T

  Returns a random element from `a` using the given state.

  See also:

  - sample proc that uses the default random number generator
  - sample proc that uses a cumulative distribution function
  - sample proc for sets

  Examples:

      let marbles = ["red", "blue", "green", "yellow", "purple"]
      var r = initRand(456)
      doAssert r.sample(marbles) == "blue"
      doAssert r.sample(marbles) == "yellow"
      doAssert r.sample(marbles) == "red"

  Source Edit

    proc sample[T](a: openArray[T]): T

  Returns a random element from `a`.

  If randomize has not been called, the order of outcomes from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - sample proc that uses a provided state
  - sample proc that uses a cumulative distribution function
  - sample proc for sets

  Examples:

      let marbles = ["red", "blue", "green", "yellow", "purple"]
      randomize(456)
      doAssert sample(marbles) == "blue"
      doAssert sample(marbles) == "yellow"
      doAssert sample(marbles) == "red"

  Source Edit

    proc sample[T, U](r: var Rand; a: openArray[T]; cdf: openArray[U]): T

  Returns an element from `a` using a cumulative distribution function (CDF) and the given state.

  The `cdf` argument does not have to be normalized, and it could contain any type of elements that can be converted to a `float`. It must be the same length as `a`. Each element in `cdf` should be greater than or equal to the previous element.

  The outcome of the cumsum proc and the return value of the cumsummed proc, which are both in the math module, can be used as the `cdf` argument.

  See also:

  - sample proc that also utilizes a CDF but uses the default random number generator
  - sample proc that does not use a CDF
  - sample proc for sets

  Examples:

      from 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)
      doAssert r.sample(marbles, cdf) == "red"
      doAssert r.sample(marbles, cdf) == "green"
      doAssert r.sample(marbles, cdf) == "blue"

  Source Edit

    proc sample[T, U](a: openArray[T]; cdf: openArray[U]): T

  Returns an element from `a` using a cumulative distribution function (CDF).

  This proc works similarly to sample[T, U](Rand, openArray[T], openArray[U]). See that proc's documentation for more details.

  If randomize has not been called, the order of outcomes from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - sample proc that also utilizes a CDF but uses a provided state
  - sample proc that does not use a CDF
  - sample proc for sets

  Examples:

      from math import cumsummed

      let marbles = ["red", "blue", "green", "yellow", "purple"]
      let count = [1, 6, 8, 3, 4]
      let cdf = count.cumsummed
      randomize(789)
      doAssert sample(marbles, cdf) == "red"
      doAssert sample(marbles, cdf) == "green"
      doAssert sample(marbles, cdf) == "blue"

  Source Edit

    proc initRand(seed: int64): Rand {...}{.raises: [], tags: [].}

  Initializes a new Rand state using the given seed.

  `seed` must not be zero. Providing a specific seed will produce the same results for that seed each time.

  The resulting state is independent of the default random number generator's state.

  See also:

  - randomize proc that accepts a seed for the default random number generator
  - randomize proc that initializes the default random number generator using the current time

  Examples:

      from times import getTime, toUnix, nanosecond

      var r1 = initRand(123)
      let now = getTime()
      var r2 = initRand(now.toUnix * 1000000000 + now.nanosecond)

  Source Edit

    proc randomize(seed: int64) {...}{.gcsafe, locks: 0, raises: [], tags: [].}

  Initializes the default random number generator with the given seed.

  `seed` must not be zero. Providing a specific seed will produce the same results for that seed each time.

  See also:

  - initRand proc
  - randomize proc that uses the current time instead

  Examples:

      from times import getTime, toUnix, nanosecond

      randomize(123)
      let now = getTime()
      randomize(now.toUnix * 1000000000 + now.nanosecond)

  Source Edit

    proc shuffle[T](r: var Rand; x: var openArray[T])

  Shuffles a sequence of elements in-place using the given state.

  See also:

  - shuffle proc that uses the default random number generator

  Examples:

      var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
      var r = initRand(678)
      r.shuffle(cards)
      doAssert cards == ["King", "Ace", "Queen", "Ten", "Jack"]

  Source Edit

    proc shuffle[T](x: var openArray[T])

  Shuffles a sequence of elements in-place.

  If randomize has not been called, the order of outcomes from this proc will always be the same.

  This proc uses the default random number generator. Thus, it is not thread-safe.

  See also:

  - shuffle proc that uses a provided state

  Examples:

      var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
      randomize(678)
      shuffle(cards)
      doAssert cards == ["King", "Ace", "Queen", "Ten", "Jack"]

  Source Edit

    proc randomize() {...}{.gcsafe, locks: 0, raises: [], tags: [TimeEffect].}

  Initializes the default random number generator with a value based on the current time.

  This proc only needs to be called once, and it should be called before the first usage of procs from this module that use the default random number generator.

  Note: Does not work for NimScript.

  See also:

  - randomize proc that accepts a seed
  - initRand proc
  Source Edit