class Random
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 Random.srand
.
The class method Random.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.
Random.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.
Constants
- DEFAULT
Public Class Methods
Creates a new PRNG using seed
to set the initial state. If seed
is omitted, the generator is initialized with Random.new_seed
.
See Random.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 (rb_check_arity(argc, 0, 1) == 0) { rb_check_frozen(obj); vseed = random_seed(); } else { vseed = argv[0]; rb_check_copyable(obj, vseed); vseed = rb_to_int(vseed); } rnd->seed = rand_init(&rnd->mt, vseed); return obj; }
Returns an arbitrary seed value. This is used by Random.new
when no seed value is specified as an argument.
Random.new_seed #=> 115032730400174366788466674494640623225
static VALUE random_seed(void) { VALUE v; uint32_t buf[DEFAULT_SEED_CNT+1]; fill_random_seed(buf, DEFAULT_SEED_CNT); v = make_seed_value(buf, DEFAULT_SEED_CNT); explicit_bzero(buf, DEFAULT_SEED_LEN); return v; }
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 (rb_check_arity(argc, 0, 1) == 0) { seed = random_seed(); } else { seed = rb_to_int(argv[0]); } old = r->seed; r->seed = rand_init(&r->mt, seed); return old; }
Public Instance Methods
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 (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 rb_equal(r1->seed, r2->seed); }
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; }