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.
Defined Under Namespace
Modules: Formatter
Constant Summary collapse
- DEFAULT =
rand_default
Class Method Summary collapse
-
.new_seed ⇒ Integer
Returns an arbitrary seed value.
-
.rand(*args) ⇒ Object
Alias of Random::DEFAULT.rand.
-
.raw_seed(size) ⇒ String
Returns a raw seed string, using platform providing features.
-
.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:.
Methods included from Formatter
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.
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'random.c', line 429
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
617 618 619 620 621 622 623 |
# File 'random.c', line 617
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.
1425 1426 1427 1428 1429 1430 1431 |
# File 'random.c', line 1425
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;
}
|
.raw_seed(size) ⇒ String
Returns a raw seed string, using platform providing features.
Random.raw_seed(8) #=> "\x78\x41\xBA\xAF\x7D\xEA\xD8\xEA"
632 633 634 635 636 637 638 639 640 |
# File 'random.c', line 632
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;
}
|
.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]
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 |
# File 'random.c', line 793
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
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 |
# File 'random.c', line 1352
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
1027 1028 1029 1030 1031 |
# File 'random.c', line 1027
static VALUE
random_bytes(VALUE obj, VALUE len)
{
return genrand_bytes(get_rnd(obj), NUM2LONG(rb_to_int(len)));
}
|
#initialize_copy(orig) ⇒ Object
:nodoc:
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 |
# File 'random.c', line 663
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:
704 705 706 707 708 709 |
# File 'random.c', line 704
static VALUE
random_left(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
return INT2FIX(rnd->mt.left);
}
|
#marshal_dump ⇒ Object (private)
:nodoc:
719 720 721 722 723 724 725 726 727 728 729 730 |
# File 'random.c', line 719
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:
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 |
# File 'random.c', line 733
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.
1265 1266 1267 1268 1269 1270 1271 |
# File 'random.c', line 1265
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;
}
|
#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
656 657 658 659 660 |
# File 'random.c', line 656
static VALUE
random_get_seed(VALUE obj)
{
return get_rnd(obj)->seed;
}
|
#state ⇒ Object (private)
:nodoc:
689 690 691 692 693 694 |
# File 'random.c', line 689
static VALUE
random_state(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
return mt_state(&rnd->mt);
}
|