module Random

Overview

Random provides an interface for random values generation, using a pseudo random number generator (PRNG).

Random.rand    # => 0.167595
Random.rand(5) # => 2

The above methods delegate to a Random instance.

r = Random.new
r.rand      # => 0.0372991
r.next_bool # => true
r.next_int  # => 2223112

This module also defines a global method #rand, which Array#sample and Array#shuffle delegates.

rand     # => 0.293829
rand(10) # => 8

An instance of each class that includes Random is a random number generator with its own state. Usually such RNGs can be initialized with a seed, which defines their initial state. It is guaranteed that after initializing two different instances with the same seed, and then executing the same calls on both of them, you will get the same results. This allows exactly reproducing the same seemingly random events by just keeping the seed.

It is possible to make a custom RNG by including Random and implementing #next_u to return an unsigned number of a pre-determined type (usually UInt32). The numbers generated by your RNG must be uniformly distributed in the whole range of possible values for that type (e.g. 0u32..UInt32::MAX). This allows all other methods of Random to be based on this and still produce uniformly distributed results. Your Random class should also have a way to initialize it. For pseudo-random number generators that will usually be an integer seed, but there are no rigid requirements for the initialization.

The default PRNG is Random::PCG32 which has a good overall statistical distribution (low bias of generated numbers) and is fast for overall usages on different platforms, but isn't cryptographically secure. If a third party has access to some generated numbers, she may deduce incoming numbers, putting your application at risk.

It is recommended to use a secure source, such as Random::Secure, Random::ISAAC or ChaCha20 for anything that needs security, such as online games, identification tokens, salts, initializing a PRNG, ... These PRNG are slower but cryptographically secure, so a third party can't deduce incoming numbers.

Direct including types

Defined in:

random/secure.cr
random.cr

Constant Summary

DEFAULT = PCG32.new

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(seed, sequence = 0_u64) #

Initializes an instance with the given seed and sequence.


[View source]
def self.new #

Initializes an instance seeded from a system source.


[View source]

Class Method Detail

def self.rand(x) #

[View source]
def self.rand : Float64 #

See #rand.


[View source]

Instance Method Detail

def base64(n : Int = 16) : String #

Generates n random bytes that are encoded into base64.

Check Base64#strict_encode for details.

Random::Secure.base64(4) # => "fK1eYg=="

It is recommended to use the secure Random::Secure as a source or another cryptographically quality PRNG such as Random::ISAAC or ChaCha20.


[View source]
def hex(n : Int = 16) : String #

Generates a hexadecimal string based on n random bytes.

The bytes are encoded into a string of two-digit hexadecimal number (00-ff) per byte.

Random::Secure.hex    # => "05f100a1123f6bdbb427698ab664ff5f"
Random::Secure.hex(1) # => "1a"

It is recommended to use the secure Random::Secure as a source or another cryptographically quality PRNG such as Random::ISAAC or ChaCha20.


[View source]
def next_bool : Bool #

Generates a random Bool.

Random.new.next_bool # => true

[View source]
def next_float : Float64 #

See #rand.


[View source]
def next_int : Int32 #

[View source]
abstract def next_u : UInt #

Generates a random unsigned integer.

The integers must be uniformly distributed between 0 and the maximal value for the chosen type.


[View source]
def rand(max : Int) : Int #

Generates a random integer which is greater than or equal to 0 and less than max.

The return type always matches the supplied argument.

Random.new.rand(10)   # => 5
Random.new.rand(5000) # => 2243

[View source]
def rand(max : Float) : Float64 #

Returns a random Float64 which is greater than or equal to 0 and less than max.

Random.new.rand(3.5)    # => 2.88938
Random.new.rand(10.725) # => 7.70147

[View source]
def rand(range : Range(Int, Int)) : Int #

Returns a random integer in the given range.

The return type always matches the supplied argument.

Random.new.rand(10..20)                 # => 14
Random.new.rand(Int64::MIN..Int64::MAX) # => -5297435808626736140

[View source]
def rand(range : Range(Float, Float)) : Float64 #

Returns a random Float64 in the given range.

Random.new.rand(6.2..21.768) # => 15.2989

[View source]
def rand : Float64 #

Generates a random Float64 between 0 and 1.

r = Random.new
r.rand # => 0.167595
r.rand # => 0.0372991

[View source]
def random_bytes(n : Int = 16) : Bytes #

Generates a slice filled with n random bytes.

Random.new.random_bytes    # => [145, 255, 191, 133, 132, 139, 53, 136, 93, 238, 2, 37, 138, 244, 3, 216]
Random.new.random_bytes(4) # => [217, 118, 38, 196]

[View source]
def random_bytes(buf : Bytes) : Nil #

Fills a given slice with random bytes.

slice = Bytes.new(4) # => [0, 0, 0, 0]
Random.new.random_bytes(slice)
slice # => [217, 118, 38, 196]

[View source]
def urlsafe_base64(n : Int = 16, padding = false) : String #

URL-safe variant of #base64.

Check Base64#urlsafe_encode for details.

Random::Secure.urlsafe_base64                    # => "MAD2bw8QaBdvITCveBNCrw"
Random::Secure.urlsafe_base64(8, padding: true)  # => "vvP1kcs841I="
Random::Secure.urlsafe_base64(16, padding: true) # => "og2aJrELDZWSdJfVGkxNKw=="

It is recommended to use the secure Random::Secure as a source or another cryptographically quality PRNG such as Random::ISAAC or ChaCha20.


[View source]