Standard library menu

Random numbers

Games roll dice, shuffle cards and spawn things in different places each time. This module gives your program dice.

By the end of this page you will

  • Roll a number in a range, such as a six-sided die.
  • Get a random decimal and a random true-or-false.
  • Shuffle a list.
  • Know why this must never be used for passwords.

What “pseudo-random” means

The numbers look random, but a computer makes them with a formula, so they are really pretend random. That is perfect for dice and games. It is not good enough for secrets, because someone clever could work out the formula. The warning below says so too.

Pseudo-random integers, doubles and booleans. Not prelude: it needs import random;.

Import
import random;

How it is seeded

The runtime keeps one generator for the whole program. It seeds itself from the operating system’s entropy the first time you draw a number, and every draw advances it. There is nothing to call first, and two runs of the same program give different numbers.

The corollary is that you cannot choose the seed, so a sequence cannot be reproduced. A test or simulation that needs repeatable “random” data must supply its own generator (a few lines of arithmetic on an int it keeps).

Functions

random_int

random_int(min: int, max: int): int

A pseudo-random integer from min to max, both included. random_int(1, 6) is a die roll, and random_int(5, 5) is always 5.

  • max < min panics, because no value fits. The message starts with your call’s file:line::

    dice.tr:10: random_int: max (3) is less than min (7)
  • Any two ints work, up to the whole range of int, and every value in the range can occur.

  • A range of fewer than 2^62 values is served by draw % width from a 62-bit draw, which favours the low end by less than one part in 2^30: not noticeable for dice, shuffles or sampling, but not suitable for a statistical test of uniformity. A wider range draws whole 64-bit values and keeps the first one inside it, which is exact.

random_double

random_double(): double

A pseudo-random double from 0.0 up to, but not including, 1.0. Multiply and add to scale it: lo + random_double() * (hi - lo).

random_bool

random_bool(): bool

true or false, each about half the time.

reseed

reseed(): void

Discards the current state and draws a fresh seed from the operating system. You never need it for correct output; it exists to start a new sequence on purpose.

RAND_MAX: int

2147483647 (2^31 - 1), the largest value one draw of the underlying generator produces (random_int combines several). It is the same on every platform.

Example: dealing and rolling

random_dealing_and_rolling.tr
import random;fn main(): int {    immut die: int = random::random_int(1, 6);    printline("you rolled " + (die to string));    immut chance: double = random::random_double();    if chance < 0.25 {        printline("a lucky roll");    }    if random::random_bool() {        printline("heads");    } else {        printline("tails");    }    // A temperature between 15.0 and 25.0.    immut celsius: double = 15.0 + random::random_double() * 10.0;    printline(celsius >= 15.0 && celsius < 25.0);   // true    return 0;}

Example: a shuffle

Shuffling a list is the standard use of random_int with a shrinking range: walk from the end and swap each element with a random one at or before it.

random_shuffle.tr
import random;import list::List;fn main(): int {    mut deck: List<int> = List::default();    mut n: int = 1;    while n <= 5 {        deck.push(n);        n = n + 1;    }    mut i: int = deck.length() - 1;    while i > 0 {        immut j: int = random::random_int(0, i);        immut held: int = deck.get(i);        deck.set(i, deck.get(j));        deck.set(j, held);        i = i - 1;    }    mut line: string = "";    mut k: int = 0;    while k < deck.length() {        line = line + (deck.get(k) to string) + " ";        k = k + 1;    }    printline(line);   // for example: 3 5 1 4 2    return 0;}
Esc

Type to search.