| .. | ||
| src | ||
| test | ||
| mrbgem.rake | ||
| README.md | ||
mruby-random
mruby-random is an mrbgem that provides pseudo-random number generation facilities for mruby.
Features
- Provides
Kernel#randmethod 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):
r = rand
p r # => 0.31415926535
To generate a pseudo-random integer number between 0 (inclusive) and a given maximum integer (exclusive):
r = rand(100)
p r # => 42
To generate a pseudo-random integer within a given Range:
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:
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:
rng = Random.new
p rng.rand(100)
Or you can provide a specific seed:
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).
rng = Random.new p rng.rand # => 0.123456789 -
Called with an integer
maxargument, it returns a pseudo-random integer between 0 (inclusive) andmax(exclusive).rng = Random.new p rng.rand(50) # => 23 -
Called with a
Rangeargument (min..maxormin...max), it returns a pseudo-random integer within that range (inclusive ofmin, and inclusive or exclusive ofmaxdepending on the range type).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.
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.
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):
p Random.rand # => 0.7654321 -
With an integer
maxargument, returns an integer between 0 andmax(exclusive ofmax):p Random.rand(10) # => 7 -
With a
Rangeargument, returns an integer within the range: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.
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.
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.
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.
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.
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.
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.a = ["apple", "banana", "cherry", "date"] p a.sample # => "cherry" (example output) empty_array = [] p empty_array.sample # => nil -
When called with an integer
nas an argument, it returns a new array containingnunique 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.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
Randominstance using therandom:keyword argument for both forms ofsample.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
- On 32-bit platforms (
- 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.