Back to Mruby

mruby-random

mrbgems/mruby-random/README.md

4.0.08.4 KB
Original Source

mruby-random

mruby-random is an mrbgem that provides pseudo-random number generation facilities for mruby.

Features

  • Provides Kernel#rand method for generating pseudo-random numbers.
  • Supports generating random numbers within a specific range.
  • Allows setting a seed for reproducible random number sequences using Kernel#srand.

Global Random Number Generation

Generating a random number

To generate a pseudo-random floating-point number between 0.0 (inclusive) and 1.0 (exclusive):

ruby
r = rand
p r # => 0.31415926535

To generate a pseudo-random integer number between 0 (inclusive) and a given maximum integer (exclusive):

ruby
r = rand(100)
p r # => 42

To generate a pseudo-random integer within a given Range:

ruby
r = rand(10..20) # or rand(10...20)
p r # => 15 (e.g., between 10 and 20, or 10 and 19)

Seeding the random number generator

To initialize the pseudo-random number generator with a specific seed:

ruby
srand(12345)
p rand(100) # => 81
p rand(100) # => 81 (if you re-seed with srand(12345) again)

# Using the same seed will produce the same sequence of random numbers
srand(12345)
p rand(100) # => 81
srand(12345)
p rand(100) # => 81

The Random Class

Besides the global Kernel#rand and Kernel#srand methods, mruby-random also provides a Random class for managing separate random number generators.

Creating an Instance

You can create a new instance of the Random class with a system-generated seed:

ruby
rng = Random.new
p rng.rand(100)

Or you can provide a specific seed:

ruby
rng = Random.new(12345)
p rng.rand(100) # => 81

Instance Methods

rand

The rand instance method behaves similarly to Kernel#rand, but operates on the specific Random instance.

  • Called with no arguments, it returns a pseudo-random floating-point number between 0.0 (inclusive) and 1.0 (exclusive).

    ruby
    rng = Random.new
    p rng.rand # => 0.123456789
    
  • Called with an integer max argument, it returns a pseudo-random integer between 0 (inclusive) and max (exclusive).

    ruby
    rng = Random.new
    p rng.rand(50) # => 23
    
  • Called with a Range argument (min..max or min...max), it returns a pseudo-random integer within that range (inclusive of min, and inclusive or exclusive of max depending on the range type).

    ruby
    rng = Random.new
    p rng.rand(10..20) # => 15 (between 10 and 20, inclusive)
    p rng.rand(10...20) # => 12 (between 10 and 19, inclusive)
    

srand

The srand instance method is used to seed the specific Random instance. It allows you to re-initialize the random number generator for that instance with a specific seed, making its sequence of generated numbers predictable.

ruby
rng = Random.new(111)
p rng.rand(1000) # => 100
p rng.rand(1000) # => 283

rng.srand(111) # Re-seed the same instance
p rng.rand(1000) # => 100 (sequence repeats for this instance)

rng2 = Random.new(111) # A different instance with the same seed
p rng2.rand(1000) # => 100

It is important to note that Random#srand is an alias for Random#initialize. Re-seeding an existing Random object will reset its internal state.

bytes(n)

The bytes method returns a string containing n pseudo-random bytes.

ruby
rng = Random.new
p rng.bytes(5) # => "\xAB\xCD\xEF\x12\x34" (example output)

Class Methods (Using the Default Generator)

The Random class also provides class methods that operate on a global, default random number generator. This is the same generator used by Kernel#rand and Kernel#srand.

Random.rand

This method is equivalent to Kernel.rand (or simply rand).

  • With no arguments, returns a float between 0.0 and 1.0 (exclusive of 1.0):

    ruby
    p Random.rand # => 0.7654321
    
  • With an integer max argument, returns an integer between 0 and max (exclusive of max):

    ruby
    p Random.rand(10) # => 7
    
  • With a Range argument, returns an integer within the range:

    ruby
    p Random.rand(50..60) # => 53
    

Random.srand(seed)

This method is equivalent to Kernel.srand(seed) (or simply srand(seed)). It seeds the global default random number generator.

ruby
Random.srand(123)
p Random.rand(100) # => 13
p rand(100)        # => 80 (uses the same seeded generator)

Random.srand(123)
p Random.rand(100) # => 13 (sequence repeats)

Random.bytes(n)

This method returns a string containing n pseudo-random bytes, generated by the global default random number generator.

ruby
p Random.bytes(3) # => "\xDE\xAD\xBE" (example output)

Array Methods

mruby-random extends the Array class with methods for shuffling elements and sampling random elements. These methods can optionally accept a Random instance to use a specific random number generator.

shuffle

The shuffle method returns a new array with the elements of the original array in a random order.

ruby
a = [1, 2, 3, 4, 5]
p a.shuffle # => [3, 1, 5, 2, 4] (example output)
p a         # => [1, 2, 3, 4, 5] (original array is unchanged)

You can provide a specific Random instance using the random: keyword argument. This is useful for reproducible shuffling.

ruby
rng = Random.new(123)
a = [1, 2, 3, 4, 5]
p a.shuffle(random: rng) # => [1, 5, 3, 2, 4] (example output, will be consistent with seed 123)

rng2 = Random.new(123) # Same seed
p a.shuffle(random: rng2) # => [1, 5, 3, 2, 4] (same shuffled order)

shuffle!

The shuffle! method shuffles the elements of the array in-place. It modifies the original array.

ruby
a = [1, 2, 3, 4, 5]
p a.shuffle! # => [4, 2, 1, 5, 3] (example output)
p a          # => [4, 2, 1, 5, 3] (original array is modified)

Similarly to shuffle, you can provide a specific Random instance using the random: keyword argument.

ruby
rng = Random.new(456)
a = [:a, :b, :c, :d, :e]
p a.shuffle!(random: rng) # => [:c, :a, :e, :d, :b] (example output, consistent with seed 456)
p a                       # => [:c, :a, :e, :d, :b] (original array is modified)

sample

The sample method chooses one or more random elements from the array.

  • When called with no arguments, it returns a single random element from the array. If the array is empty, it returns nil.

    ruby
    a = ["apple", "banana", "cherry", "date"]
    p a.sample # => "cherry" (example output)
    
    empty_array = []
    p empty_array.sample # => nil
    
  • When called with an integer n as an argument, it returns a new array containing n unique random elements from the original array. If the array does not have enough unique elements, it returns all elements in a shuffled order. If the array is empty, it returns an empty array.

    ruby
    a = ["apple", "banana", "cherry", "date", "elderberry"]
    p a.sample(3) # => ["date", "apple", "banana"] (example output)
    p a.sample(10) # => ["banana", "elderberry", "apple", "date", "cherry"] (all elements, shuffled)
    
    
    empty_array = []
    p empty_array.sample(3) # => []
    
  • You can provide a specific Random instance using the random: keyword argument for both forms of sample.

    ruby
    rng = Random.new(789)
    a = [10, 20, 30, 40, 50]
    p a.sample(random: rng)    # => 30 (example output, consistent with seed 789)
    
    rng_b = Random.new(789) # Re-initialize with the same seed for predictable multi-sampling
    p a.sample(2, random: rng_b) # => [30, 50] (example output)
    

Algorithm

The mruby-random mrbgem uses the PCG-XSH-RR (Permuted Congruential Generator - XorShift High, Random Rotate) algorithm for pseudo-random number generation.

Key Features

  • Compact State: Uses only 64 bits of state (compared to 128 bits in the previous xoshiro128++ implementation), reducing memory footprint by 50%
  • Excellent Statistical Quality: Passes rigorous statistical test suites (TestU01, PractRand)
  • Platform-Optimized: Automatically adapts to platform characteristics for optimal performance
    • On 32-bit platforms (MRB_32BIT): Uses an optimized 32-bit multiplier that requires only 2 multiply operations instead of 3
    • On 64-bit platforms: Uses the standard 64-bit multiplier for maximum statistical quality
  • Fast Performance: Competitive speed with modern PRNG algorithms while maintaining smaller memory footprint

The PCG family of algorithms was developed by Melissa O'Neill and is widely used in production systems. For more details, see https://www.pcg-random.org/.

License

The mruby-random mrbgem is released under the MIT License. See the LICENSE file for details.