Class: Random
Overview
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.
Constant Summary collapse
- DEFAULT =
Direct access to Ruby’s Pseudorandom number generator (PRNG).
rand_default
Class Method Summary collapse
-
.new_seed ⇒ Integer
Returns an arbitrary seed value.
-
.rand(*args) ⇒ Object
Alias of Random::DEFAULT.rand.
-
.srand(number = Random.new_seed) ⇒ Object
Seeds the system pseudo-random number generator, Random::DEFAULT, with
number
.
Instance Method Summary collapse
-
#==(prng2) ⇒ Boolean
Returns true if the two generators have the same internal state, otherwise false.
-
#bytes(size) ⇒ String
Returns a random binary string containing
size
bytes. -
#new(seed = Random.new_seed) ⇒ Object
constructor
Creates a new PRNG using
seed
to set the initial state. -
#initialize_copy(orig) ⇒ Object
:nodoc:.
-
#left ⇒ Object
private
:nodoc:.
-
#marshal_dump ⇒ Object
private
:nodoc:.
-
#marshal_load(dump) ⇒ Object
private
:nodoc:.
-
#rand(*args) ⇒ Object
When
max
is an Integer,rand
returns a random integer greater than or equal to zero and less thanmax
. -
#seed ⇒ Integer
Returns the seed value used to initialize the generator.
-
#state ⇒ Object
private
:nodoc:.
Constructor Details
#new(seed = Random.new_seed) ⇒ Object
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.
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'random.c', line 410
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;
}
|
Class Method Details
.new_seed ⇒ Integer
Returns an arbitrary seed value. This is used by Random.new when no seed value is specified as an argument.
Random.new_seed #=> 115032730400174366788466674494640623225
519 520 521 522 523 524 525 |
# File 'random.c', line 519
static VALUE
random_seed(void)
{
uint32_t buf[DEFAULT_SEED_CNT];
fill_random_seed(buf);
return make_seed_value(buf);
}
|
.rand ⇒ Float .rand(max) ⇒ Numeric
Alias of Random::DEFAULT.rand.
1224 1225 1226 1227 1228 |
# File 'random.c', line 1224
static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
return rand_random(argc, argv, rand_start(&default_rand));
}
|
.srand(number = Random.new_seed) ⇒ Object
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]
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 |
# File 'random.c', line 678
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;
}
|
Instance Method Details
#==(prng2) ⇒ Boolean
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
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 |
# File 'random.c', line 1151
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;
}
|
#bytes(size) ⇒ String
869 870 871 872 873 |
# File 'random.c', line 869
static VALUE
random_bytes(VALUE obj, VALUE len)
{
return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
}
|
#initialize_copy(orig) ⇒ Object
:nodoc:
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'random.c', line 548
static VALUE
random_copy(VALUE obj, VALUE orig)
{
rb_random_t *rnd1, *rnd2;
struct MT *mt;
if (!OBJ_INIT_COPY(obj, orig)) return obj;
rnd1 = get_rnd(obj);
rnd2 = get_rnd(orig);
mt = &rnd1->mt;
*rnd1 = *rnd2;
mt->next = mt->state + numberof(mt->state) - mt->left + 1;
return obj;
}
|
#left ⇒ Object (private)
:nodoc:
589 590 591 592 593 594 |
# File 'random.c', line 589
static VALUE
random_left(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
return INT2FIX(rnd->mt.left);
}
|
#marshal_dump ⇒ Object (private)
:nodoc:
604 605 606 607 608 609 610 611 612 613 614 615 |
# File 'random.c', line 604
static VALUE
random_dump(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
VALUE dump = rb_ary_new2(3);
rb_ary_push(dump, mt_state(&rnd->mt));
rb_ary_push(dump, INT2FIX(rnd->mt.left));
rb_ary_push(dump, rnd->seed);
return dump;
}
|
#marshal_load(dump) ⇒ Object (private)
:nodoc:
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
# File 'random.c', line 618
static VALUE
random_load(VALUE obj, VALUE dump)
{
rb_random_t *rnd = get_rnd(obj);
struct MT *mt = &rnd->mt;
VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
const VALUE *ary;
unsigned long x;
rb_check_copyable(obj, dump);
Check_Type(dump, T_ARRAY);
ary = RARRAY_CONST_PTR(dump);
switch (RARRAY_LEN(dump)) {
case 3:
seed = ary[2];
case 2:
left = ary[1];
case 1:
state = ary[0];
break;
default:
rb_raise(rb_eArgError, "wrong dump data");
}
rb_integer_pack(state, mt->state, numberof(mt->state),
sizeof(*mt->state), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
x = NUM2ULONG(left);
if (x > numberof(mt->state)) {
rb_raise(rb_eArgError, "wrong value");
}
mt->left = (unsigned int)x;
mt->next = mt->state + numberof(mt->state) - x + 1;
rnd->seed = rb_to_int(seed);
return obj;
}
|
#rand ⇒ Float #rand(max) ⇒ Numeric
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.
1080 1081 1082 1083 1084 |
# File 'random.c', line 1080
static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
return rand_random(argc, argv, get_rnd(obj));
}
|
#seed ⇒ Integer
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
541 542 543 544 545 |
# File 'random.c', line 541
static VALUE
random_get_seed(VALUE obj)
{
return get_rnd(obj)->seed;
}
|
#state ⇒ Object (private)
:nodoc:
574 575 576 577 578 579 |
# File 'random.c', line 574
static VALUE
random_state(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
return mt_state(&rnd->mt);
}
|