Random provides an interface to Ruby's pseudo-random number generator, or PRNG. The PRNG produces a deterministic sequence of bits which approximate true randomness. The sequence may be represented by integers, floats, or binary strings.
The generator may be initialized with either a system-generated or user-supplied seed value by using ::srand.
The class method #rand provides the base functionality of Kernel#rand along with better handling of floating point values. These are both interfaces to Random::DEFAULT, the Ruby system PRNG.
::new will create a new PRNG with a state independent of Random::DEFAULT, allowing multiple generators with different seed values or sequence positions to exist simultaneously. Random objects can be marshaled, allowing sequences to be saved and resumed.
PRNGs are currently implemented as a modified Mersenne Twister with a period of 2**19937-1.
Creates a new PRNG using seed
to set the initial state. If
seed
is omitted, the generator is initialized with ::new_seed.
See ::srand for more information on the use of seed values.
static VALUE random_init(int argc, VALUE *argv, VALUE obj) { VALUE vseed; rb_random_t *rnd = get_rnd(obj); if (argc == 0) { rb_check_frozen(obj); vseed = random_seed(); } else { rb_scan_args(argc, argv, "01", &vseed); rb_check_copyable(obj, vseed); } rnd->seed = rand_init(&rnd->mt, vseed); return obj; }
Returns an arbitrary seed value. This is used by ::new when no seed value is specified as an argument.
Random.new_seed #=> 115032730400174366788466674494640623225
static VALUE random_seed(void) { uint32_t buf[DEFAULT_SEED_CNT]; fill_random_seed(buf); return make_seed_value(buf); }
Alias of Random::DEFAULT.rand.
static VALUE random_s_rand(int argc, VALUE *argv, VALUE obj) { VALUE v = rand_random(argc, argv, Qnil, rand_start(&default_rand)); check_random_number(v, argv); return v; }
Returns a raw seed string, using platform providing features.
Random.raw_seed(8) #=> "\x78\x41\xBA\xAF\x7D\xEA\xD8\xEA"
static VALUE random_raw_seed(VALUE self, VALUE size) { long n = NUM2ULONG(size); VALUE buf = rb_str_new(0, n); if (n == 0) return buf; if (fill_random_bytes(RSTRING_PTR(buf), n, FALSE)) return Qnil; return buf; }
Seeds the system pseudo-random number generator, Random::DEFAULT, with
number
. The previous seed value is returned.
If number
is omitted, seeds the generator using a source of
entropy provided by the operating system, if available (/dev/urandom on
Unix systems or the RSA cryptographic provider on Windows), which is then
combined with the time, the process id, and a sequence number.
srand may be used to ensure repeatable sequences of pseudo-random numbers between different runs of the program. By setting the seed to a known value, programs can be made deterministic during testing.
srand 1234 # => 268519324636777531569100071560086917274 [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319] [ rand(10), rand(1000) ] # => [4, 664] srand 1234 # => 1234 [ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
static VALUE rb_f_srand(int argc, VALUE *argv, VALUE obj) { VALUE seed, old; rb_random_t *r = &default_rand; if (argc == 0) { seed = random_seed(); } else { rb_scan_args(argc, argv, "01", &seed); } old = r->seed; r->seed = rand_init(&r->mt, seed); return old; }
Returns true if the two generators have the same internal state, otherwise false. Equivalent generators will return the same sequence of pseudo-random numbers. Two generators will generally have the same state only if they were initialized with the same seed
Random.new == Random.new # => false Random.new(1234) == Random.new(1234) # => true
and have the same invocation history.
prng1 = Random.new(1234) prng2 = Random.new(1234) prng1 == prng2 # => true prng1.rand # => 0.1915194503788923 prng1 == prng2 # => false prng2.rand # => 0.1915194503788923 prng1 == prng2 # => true
static VALUE random_equal(VALUE self, VALUE other) { rb_random_t *r1, *r2; if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse; r1 = get_rnd(self); r2 = get_rnd(other); if (!RTEST(rb_funcall2(r1->seed, rb_intern("=="), 1, &r2->seed))) return Qfalse; if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse; if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse; if (r1->mt.left != r2->mt.left) return Qfalse; return Qtrue; }
Returns a random binary string containing size
bytes.
random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO" random_string.size # => 10
static VALUE random_bytes(VALUE obj, VALUE len) { return genrand_bytes(get_rnd(obj), NUM2LONG(rb_to_int(len))); }
When max
is an Integer,
rand
returns a random integer greater than or equal to zero
and less than max
. Unlike Kernel#rand, when max
is
a negative integer or zero, rand
raises an ArgumentError.
prng = Random.new prng.rand(100) # => 42
When max
is a Float,
rand
returns a random floating point number between 0.0 and
max
, including 0.0 and excluding max
.
prng.rand(1.5) # => 1.4600282860034115
When max
is a Range,
rand
returns a random number where range.member?(number) ==
true.
prng.rand(5..9) # => one of [5, 6, 7, 8, 9] prng.rand(5...9) # => one of [5, 6, 7, 8] prng.rand(5.0..9.0) # => between 5.0 and 9.0, including 9.0 prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0
Both the beginning and ending values of the range must respond to subtract
(-
) and add (+
)methods, or rand will raise an ArgumentError.
static VALUE random_rand(int argc, VALUE *argv, VALUE obj) { VALUE v = rand_random(argc, argv, obj, get_rnd(obj)); check_random_number(v, argv); return v; }
Returns the seed value used to initialize the generator. This may be used to initialize another generator with the same state at a later time, causing it to produce the same sequence of numbers.
prng1 = Random.new(1234) prng1.seed #=> 1234 prng1.rand(100) #=> 47 prng2 = Random.new(prng1.seed) prng2.rand(100) #=> 47
static VALUE random_get_seed(VALUE obj) { return get_rnd(obj)->seed; }