Class: Random
Class Method Summary collapse
-
.new_seed ⇒ Integer
Returns arbitrary value for seed.
-
.rand(max = 0) ⇒ Numeric
Converts max to an integer using max1 = max
.to_i.abs
. -
.srand(number = 0) ⇒ Object
Seeds the pseudorandom number generator to the value of number.
Instance Method Summary collapse
-
#==(prng2) ⇒ Boolean
Returns true if the generators' states equal.
-
#bytes(size) ⇒ Object
Returns a random binary string.
-
#new([seed]) ⇒ Object
constructor
Creates new Mersenne Twister based pseudorandom number generator with seed.
-
#initialize_copy ⇒ Object
:nodoc:.
-
#left ⇒ Object
:nodoc:.
-
#marshal_dump ⇒ Object
:nodoc:.
-
#marshal_load ⇒ Object
:nodoc:.
-
#rand ⇒ Object
When the argument is an
Integer
or aBignum
, it returns a random integer greater than or equal to zero and less than the argument. -
#seed ⇒ Integer
Returns the seed of the generator.
-
#state ⇒ Object
:nodoc:.
Constructor Details
#new([seed]) ⇒ Object
Creates new Mersenne Twister based pseudorandom number generator with seed. When the argument seed is omitted, the generator is initialized with Random.new_seed.
The argument seed is used to ensure repeatable sequences of random numbers between different runs of the program.
prng = Random.new(1234)
[ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832]
[ prng.integer(10), prng.integer(1000) ] #=> [4, 664]
prng = Random.new(1234)
[ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832]
|
# File 'random.c'
/*
* call-seq: Random.new([seed]) -> prng
*
* Creates new Mersenne Twister based pseudorandom number generator with
* seed. When the argument seed is omitted, the generator is initialized
* with Random.new_seed.
*
* The argument seed is used to ensure repeatable sequences of random numbers
* between different runs of the program.
*
* prng = Random.new(1234)
* [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832]
* [ prng.integer(10), prng.integer(1000) ] #=> [4, 664]
* prng = Random.new(1234)
* [ prng.rand, prng.rand ] #=> [0.191519450378892, 0.622108771039832]
*/
static VALUE
random_init(int argc, VALUE *argv, VALUE obj)
{
VALUE vseed;
rb_random_t *rnd = get_rnd(obj);
if (argc == 0) {
vseed = random_seed();
}
else {
rb_scan_args(argc, argv, "01", &vseed);
}
rnd->seed = rand_init(&rnd->mt, vseed);
return obj;
}
|
Class Method Details
.new_seed ⇒ Integer
Returns arbitrary value for seed.
|
# File 'random.c'
/*
* call-seq: Random.new_seed -> integer
*
* Returns arbitrary value for seed.
*/
static VALUE
random_seed(void)
{
unsigned int buf[DEFAULT_SEED_CNT];
fill_random_seed(buf);
return make_seed_value(buf);
}
|
.rand(max = 0) ⇒ Numeric
Converts max to an integer using max1 = max.to_i.abs
. If max is nil
the result is zero, returns a pseudorandom floating point number greater than or equal to 0.0 and less than 1.0. Otherwise, returns a pseudorandom integer greater than or equal to zero and less than max1. Kernel::srand
may be used to ensure repeatable sequences of random numbers between different runs of the program. Ruby currently uses a modified Mersenne Twister with a period of 2**19937-1.
srand 1234 #=> 0
[ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
[ rand(10), rand(1000) ] #=> [6, 817]
srand 1234 #=> 1234
[ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
|
# File 'random.c'
/*
* call-seq:
* rand(max=0) -> number
*
* Converts <i>max</i> to an integer using max1 =
* max<code>.to_i.abs</code>. If _max_ is +nil+ the result is zero, returns a
* pseudorandom floating point number greater than or equal to 0.0 and
* less than 1.0. Otherwise, returns a pseudorandom integer greater
* than or equal to zero and less than max1. <code>Kernel::srand</code>
* may be used to ensure repeatable sequences of random numbers between
* different runs of the program. Ruby currently uses a modified
* Mersenne Twister with a period of 2**19937-1.
*
* srand 1234 #=> 0
* [ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
* [ rand(10), rand(1000) ] #=> [6, 817]
* srand 1234 #=> 1234
* [ rand, rand ] #=> [0.191519450163469, 0.49766366626136]
*/
static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax, r;
struct MT *mt = default_mt();
if (argc == 0) goto zero_arg;
rb_scan_args(argc, argv, "01", &vmax);
if (NIL_P(vmax)) goto zero_arg;
vmax = rb_to_int(vmax);
if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
zero_arg:
return DBL2NUM(genrand_real(mt));
}
return r;
}
|
.srand(number = 0) ⇒ Object
Seeds the pseudorandom number generator to the value of number. If number is omitted or zero, seeds the generator using a combination of the time, the process id, and a sequence number. (This is also the behavior if Kernel::rand
is called without previously calling srand
, but without the sequence.) By setting the seed to a known value, scripts can be made deterministic during testing. The previous seed value is returned. Also see Kernel::rand
.
|
# File 'random.c'
/*
* call-seq:
* srand(number=0) -> old_seed
*
* Seeds the pseudorandom number generator to the value of
* <i>number</i>. If <i>number</i> is omitted
* or zero, seeds the generator using a combination of the time, the
* process id, and a sequence number. (This is also the behavior if
* <code>Kernel::rand</code> is called without previously calling
* <code>srand</code>, but without the sequence.) By setting the seed
* to a known value, scripts can be made deterministic during testing.
* The previous seed value is returned. Also see <code>Kernel::rand</code>.
*/
static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
rb_random_t *r = &default_rand;
rb_secure(4);
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 generators' states equal.
|
# File 'random.c'
/*
* call-seq:
* prng1 == prng2 -> true or false
*
* Returns true if the generators' states equal.
*/
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) ⇒ Object
Returns a random binary string. The argument size specified the length of the result string.
|
# File 'random.c'
/*
* call-seq: prng.bytes(size) -> prng
*
* Returns a random binary string. The argument size specified the length of
* the result string.
*/
static VALUE
random_bytes(VALUE obj, VALUE len)
{
return rb_random_bytes(obj, NUM2LONG(rb_to_int(len)));
}
|
#initialize_copy ⇒ Object
:nodoc:
|
# File 'random.c'
/* :nodoc: */
static VALUE
random_copy(VALUE obj, VALUE orig)
{
rb_random_t *rnd1 = get_rnd(obj);
rb_random_t *rnd2 = get_rnd(orig);
struct MT *mt = &rnd1->mt;
*rnd1 = *rnd2;
mt->next = mt->state + numberof(mt->state) - mt->left + 1;
return obj;
}
|
#left ⇒ Object
:nodoc:
|
# File 'random.c'
/* :nodoc: */
static VALUE
random_left(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
return INT2FIX(rnd->mt.left);
}
|
#marshal_dump ⇒ Object
:nodoc:
|
# File 'random.c'
/* :nodoc: */
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 ⇒ Object
:nodoc:
|
# File 'random.c'
/* :nodoc: */
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);
VALUE *ary;
unsigned long x;
Check_Type(dump, T_ARRAY);
ary = RARRAY_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");
}
memset(mt->state, 0, sizeof(mt->state));
if (FIXNUM_P(state)) {
x = FIX2ULONG(state);
mt->state[0] = (unsigned int)x;
#if SIZEOF_LONG / SIZEOF_INT >= 2
mt->state[1] = (unsigned int)(x >> BITSPERDIG);
#endif
#if SIZEOF_LONG / SIZEOF_INT >= 3
mt->state[2] = (unsigned int)(x >> 2 * BITSPERDIG);
#endif
#if SIZEOF_LONG / SIZEOF_INT >= 4
mt->state[3] = (unsigned int)(x >> 3 * BITSPERDIG);
#endif
}
else {
BDIGIT *d;
long len;
Check_Type(state, T_BIGNUM);
len = RBIGNUM_LEN(state);
if (len > roomof(sizeof(mt->state), SIZEOF_BDIGITS)) {
len = roomof(sizeof(mt->state), SIZEOF_BDIGITS);
}
#if SIZEOF_BDIGITS < SIZEOF_INT
else if (len % DIGSPERINT) {
d = RBIGNUM_DIGITS(state) + len;
# if DIGSPERINT == 2
--len;
x = *--d;
# else
x = 0;
do {
x = (x << BITSPERDIG) | *--d;
} while (--len % DIGSPERINT);
# endif
mt->state[len / DIGSPERINT] = (unsigned int)x;
}
#endif
if (len > 0) {
d = BDIGITS(state) + len;
do {
--len;
x = *--d;
# if DIGSPERINT == 2
--len;
x = (x << BITSPERDIG) | *--d;
# elif SIZEOF_BDIGITS < SIZEOF_INT
do {
x = (x << BITSPERDIG) | *--d;
} while (--len % DIGSPERINT);
# endif
mt->state[len / DIGSPERINT] = (unsigned int)x;
} while (len > 0);
}
}
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(limit) ⇒ Numeric
When the argument is an Integer
or a Bignum
, it returns a random integer greater than or equal to zero and less than the argument. Unlike Random.rand, when the argument is a negative integer or zero, it raises an ArgumentError.
When the argument is a Float
, it returns a random floating point number between 0.0 and max, including 0.0 and excluding max.
When the argument limit is a Range
, it 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
begin
/end
of the range have to have subtract and add methods.
Otherwise, it raises an ArgumentError.
|
# File 'random.c'
/*
* call-seq:
* prng.rand -> float
* prng.rand(limit) -> number
*
* When the argument is an +Integer+ or a +Bignum+, it returns a
* random integer greater than or equal to zero and less than the
* argument. Unlike Random.rand, when the argument is a negative
* integer or zero, it raises an ArgumentError.
*
* When the argument is a +Float+, it returns a random floating point
* number between 0.0 and _max_, including 0.0 and excluding _max_.
*
* When the argument _limit_ is a +Range+, it 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
*
* +begin+/+end+ of the range have to have subtract and add methods.
*
* Otherwise, it raises an ArgumentError.
*/
static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
VALUE vmax, beg = Qundef, v;
int excl = 0;
if (argc == 0) {
return rb_float_new(genrand_real(&rnd->mt));
}
else if (argc != 1) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..1)", argc);
}
vmax = argv[0];
if (NIL_P(vmax)) {
v = Qnil;
}
else if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
v = rand_int(&rnd->mt, vmax = v, 1);
}
else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
double max = float_value(v);
if (max > 0.0)
v = rb_float_new(max * genrand_real(&rnd->mt));
else
v = Qnil;
}
else if ((v = range_values(vmax, &beg, &excl)) != Qfalse) {
vmax = v;
if (TYPE(vmax) != T_FLOAT && (v = rb_check_to_integer(vmax, "to_int"), !NIL_P(v))) {
long max;
vmax = v;
v = Qnil;
if (FIXNUM_P(vmax)) {
fixnum:
if ((max = FIX2LONG(vmax) - excl) >= 0) {
unsigned long r = limited_rand(&rnd->mt, (unsigned long)max);
v = ULONG2NUM(r);
}
}
else if (BUILTIN_TYPE(vmax) == T_BIGNUM && RBIGNUM_SIGN(vmax) && !rb_bigzero_p(vmax)) {
vmax = excl ? rb_big_minus(vmax, INT2FIX(1)) : rb_big_norm(vmax);
if (FIXNUM_P(vmax)) {
excl = 0;
goto fixnum;
}
v = limited_big_rand(&rnd->mt, RBIGNUM(vmax));
}
}
else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
double max = float_value(v), r;
v = Qnil;
if (max > 0.0) {
if (excl) {
r = genrand_real(&rnd->mt);
}
else {
r = genrand_real2(&rnd->mt);
}
v = rb_float_new(r * max);
}
else if (max == 0.0 && !excl) {
v = rb_float_new(0.0);
}
}
}
else {
v = Qnil;
NUM2LONG(vmax);
}
if (NIL_P(v)) {
VALUE mesg = rb_str_new_cstr("invalid argument - ");
rb_str_append(mesg, rb_obj_as_string(argv[0]));
rb_exc_raise(rb_exc_new3(rb_eArgError, mesg));
}
if (beg == Qundef) return v;
if (FIXNUM_P(beg) && FIXNUM_P(v)) {
long x = FIX2LONG(beg) + FIX2LONG(v);
return LONG2NUM(x);
}
switch (TYPE(v)) {
case T_BIGNUM:
return rb_big_plus(v, beg);
case T_FLOAT: {
VALUE f = rb_check_to_float(beg);
if (!NIL_P(f)) {
RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
return v;
}
}
default:
return rb_funcall2(beg, id_plus, 1, &v);
}
}
|
#seed ⇒ Integer
Returns the seed of the generator.
|
# File 'random.c'
/*
* call-seq: prng.seed -> integer
*
* Returns the seed of the generator.
*/
static VALUE
random_get_seed(VALUE obj)
{
return get_rnd(obj)->seed;
}
|
#state ⇒ Object
:nodoc:
|
# File 'random.c'
/* :nodoc: */
static VALUE
random_state(VALUE obj)
{
rb_random_t *rnd = get_rnd(obj);
return mt_state(&rnd->mt);
}
|