Random#rand

e$B$J$+$@$G$9!#e(B

e$B:#$Ne(Btrunke$B$K$O!";n83E*$Ke(BRandome$B%/%i%9$,$"$j$^$9!#$3$l$K$Oe(Binte$B$He(B
floate$B$H$$$&%a%=%C%I$,$"$j$^$9$,!"e(BKernel#rande$B$H$N8_49@-$K7g$1$F$$e(B
e$B$?$j!“e(BRangee$B$KBP$9$kF0:n$,$o$+$j$K$/$+$C$?$j$7$^$9!#$=$3$Ge(B
Random#rande$B$KE}9g$7$?$$$H;W$&$N$G$9$,!”$$$+$,$G$7$g$&$+!#e(B

r = Random.new
r.rand #=> a float in 0.0…1.0
r.rand(max_num) #=> a number in 0.0…max_num
r.rand(range) #=> a number in range

e$B0z?t$,M?$($i$l$?>l9g$O7k2L$N%/%i%9$O0z?t$N%/%i%9$K=>$$$^$9!#e(B
Rangee$B$N>l9g$ON>C<$NCM$N:9$r;H$$$^$9!#e(B

e$B$?$@$7!"0J2<$N%Q%C%A$GBP1~$7$F$$$k$N$Oe(BIntegere$B$He(BFloate$B$N$_$G!"e(B
Complexe$B$de(BRationale$B$O07$$$^$;$s!#0lBN$I$&$$$&$b$N$,4|BT$5$l$k$N$+e(B
e$B8+Ev$,$D$+$J$$$N$G!#e(B

Index: object.c

— object.c (revision 24648)
+++ object.c (working copy)
@@ -2300,4 +2300,14 @@ rb_to_float(VALUE val)
}

+VALUE
+rb_check_to_float(VALUE val)
+{

  • if (TYPE(val) == T_FLOAT) return val;
  • if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
  • return Qnil;
  • }
  • return rb_check_convert_type(val, T_FLOAT, “Float”, “to_f”);
    +}

double
rb_num2dbl(VALUE val)
Index: random.c

— random.c (revision 24648)
+++ random.c (working copy)
@@ -179,4 +179,14 @@ genrand_real(struct MT mt)
return(a
67108864.0+b)(1.0/9007199254740992.0);
}
+
+/
generates a random number on [0,1] with 53-bit resolution*/
+static double int_pair_to_real_inclusive(unsigned int a, unsigned int
b);
+static double
+genrand_real2(struct MT *mt)
+{

  • unsigned int a = genrand_int32(mt), b = genrand_int32(mt);
  • return int_pair_to_real_inclusive(a, b);
    +}

/* These real versions are due to Isaku Wada, 2002/01/09 added */

@@ -239,4 +249,55 @@ rb_genrand_real(void)
#define SIZEOF_INT32 (31/CHAR_BIT + 1)

+static double
+int_pair_to_real_inclusive(unsigned int a, unsigned int b)
+{

  • VALUE x = rb_big_new(roomof(64, BITSPERDIG), 1);
  • VALUE m = rb_big_new(roomof(53, BITSPERDIG), 1);
  • BDIGIT *xd = BDIGITS(x);
  • int i = 0;
  • double r;
  • xd[i++] = (BDIGIT)b;
    +#if BITSPERDIG < 32
  • xd[i++] = (BDIGIT)(b >> BITSPERDIG);
    +#endif
  • xd[i++] = (BDIGIT)a;
    +#if BITSPERDIG < 32
  • xd[i++] = (BDIGIT)(a >> BITSPERDIG);
    +#endif
  • xd = BDIGITS(m);
    +#if BITSPERDIG < 53
  • MEMZERO(xd, BDIGIT, roomof(53, BITSPERDIG) - 1);
    +#endif
  • xd[53 / BITSPERDIG] = 1 << 53 % BITSPERDIG;
  • xd[0] |= 1;
  • x = rb_big_mul(x, m);
  • if (FIXNUM_P(x)) {
    +#if CHAR_BIT * SIZEOF_LONG > 64
  • r = (double)(FIX2ULONG(x) >> 64);
    +#else
  • return 0.0;
    +#endif
  • }
  • else {
    +#if 64 % BITSPERDIG == 0
  • long len = RBIGNUM_LEN(x);
  • xd = BDIGITS(x);
  • MEMMOVE(xd, xd + 64 / BITSPERDIG, BDIGIT, len - 64 / BITSPERDIG);
  • MEMZERO(xd + len - 64 / BITSPERDIG, BDIGIT, 64 / BITSPERDIG);
  • r = rb_big2dbl(x);
    +#else
  • x = rb_big_rshift(x, INT2FIX(64));
  • if (FIXNUM_P(x)) {
  •  r = (double)FIX2ULONG(x);
    
  • }
  • else {
  •  r = rb_big2dbl(x);
    
  • }
    +#endif
  • }
  • return ldexp(r, -53);
    +}

VALUE rb_cRandom;
#define id_minus ‘-’
@@ -830,17 +891,12 @@ rb_random_bytes(VALUE obj, long n)

static VALUE
-range_values(VALUE vmax, VALUE *begp)
+range_values(VALUE vmax, VALUE *begp, int *exclp)
{

  • VALUE end, r, one = INT2FIX(1);
  • int excl;
  • VALUE end, r;
  • if (!rb_range_values(vmax, begp, &end, &excl)) return Qfalse;
  • if (!rb_range_values(vmax, begp, &end, exclp)) return Qfalse;
    if (!rb_respond_to(end, id_minus)) return Qfalse;
    r = rb_funcall2(end, id_minus, 1, begp);
    if (NIL_P®) return Qfalse;
  • if (!excl && rb_respond_to(r, id_plus)) {
  • r = rb_funcall2(r, id_plus, 1, &one);
  • if (NIL_P®) return Qfalse;
  • }
    return r;
    }
    @@ -854,5 +910,5 @@ add_to_begin(VALUE beg, VALUE offset)

static VALUE
-rand_int(struct MT *mt, VALUE vmax)
+rand_int(struct MT *mt, VALUE vmax, int restrictive)
{
long max;
@@ -862,5 +918,12 @@ rand_int(struct MT *mt, VALUE vmax)
max = FIX2LONG(vmax);
if (!max) return Qnil;

  • r = limited_rand(mt, (unsigned long)(max < 0 ? -max : max) - 1);
  • if (max < 0) {
  •  if (restrictive) return Qnil;
    
  •  max = -max;
    
  • }
  • else if (max == 1 && restrictive) {
  •  return Qnil;
    
  • }
  • r = limited_rand(mt, (unsigned long)max - 1);
    return ULONG2NUM®;
    }
    @@ -869,4 +932,5 @@ rand_int(struct MT *mt, VALUE vmax)
    if (rb_bigzero_p(vmax)) return Qnil;
    if (!RBIGNUM_SIGN(vmax)) {
  •  if (restrictive) return Qnil;
     vmax = rb_big_clone(vmax);
     RBIGNUM_SET_SIGN(vmax, 1);
    

@@ -876,4 +940,5 @@ rand_int(struct MT *mt, VALUE vmax)
max = FIX2LONG(vmax);
if (max == -1) return Qnil;

  •  if (max == 0 && restrictive) return Qnil;
     r = limited_rand(mt, max);
     return LONG2NUM(r);
    

@@ -885,6 +950,19 @@ rand_int(struct MT *mt, VALUE vmax)
}

+static inline double
+float_value(VALUE v)
+{

  • double x = RFLOAT_VALUE(v);
  • if (isinf(x) || isnan(x)) {
  • VALUE error = INT2FIX(EDOM);
  • rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
  • }
  • return x;
    +}

/*

    • call-seq: prng.int(limit) -> integer
    • call-seq:
    • prng.rand -> float
      
    • prng.rand(limit) -> number
      
    • When the argument is an +Integer+ or a +Bignum+, it returns a
      @@ -893,8 +971,13 @@ rand_int(struct MT *mt, VALUE vmax)
    • 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
    • integer from integers where range.member?(integer) == true.
    • prng.int(5..9)  # => one of [5, 6, 7, 8, 9]
      
    • prng.int(5...9) # => one of [5, 6, 7, 8]
      
    • 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 subtruct and add methods.
      @@ -902,67 +985,71 @@ rand_int(struct MT *mt, VALUE vmax)
    • Otherwise, it raises an ArgumentError.
      */
      -VALUE
      -rb_random_int(VALUE obj, VALUE vmax)
      -{
  • VALUE v, beg = Qundef;
  • rb_random_t *rnd = get_rnd(obj);
  • v = rb_check_to_integer(vmax, “to_int”);
  • if (NIL_P(v)) {
  • /* range like object support */
  • if (!(v = range_values(vmax, &beg))) {
  •  v = vmax;
    
  • }
  • v = rb_to_int(v);
  • beg = rb_to_int(beg);
  • }
  • v = rand_int(&rnd->mt, v);
  • if (NIL_P(v)) v = INT2FIX(0);
  • return add_to_begin(beg, v);
    -}

-#define random_int rb_random_int

-/*

    • call-seq:
    • prng.float -> float
      
    • prng.float([max=1.0]) -> float
      
    • Returns a random floating point number between 0.0 and max,
    • including 0.0 and excluding max.
  • */
    static VALUE
    -random_float(int argc, VALUE *argv, VALUE obj)
    +random_rand(int argc, VALUE *argv, VALUE obj)
    {
  • VALUE rb_check_to_float(VALUE);
    rb_random_t *rnd = get_rnd(obj);
  • VALUE vmax, beg = Qundef;
  • double max = 0, r;
  • VALUE vmax, beg = Qundef, v;
  • int excl = 0;
  • switch (argc) {
  •  case 0:
    
  • break;
  •  case 1:
    
  • vmax = argv[0];
  • if (TYPE(vmax) == T_FLOAT ||
  •  !NIL_P(vmax = rb_to_float(vmax)) ||
    
  •  (vmax = range_values(vmax, &beg)) != Qfalse) {
    
  •  max = RFLOAT_VALUE(vmax);
    
  •  if (isinf(max) || isnan(max)) {
    
  • VALUE error = INT2FIX(EDOM);
  • rb_exc_raise(rb_class_new_instance(1, &error,
    rb_eSystemCallError));
  • if (argc == 0) {
  •  zero_arg:
    
  • 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)) {
  • goto zero_arg;
  • }
  • 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);
  • v = rb_float_new(max * genrand_real(&rnd->mt));
  • }
  • 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 {
  •  beg = Qundef;
    
  •  Check_Type(argv[0], T_FLOAT);
    
  • 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);
  •  }
    
    }
  • break;
  •  default:
    
  • rb_scan_args(argc, argv, “01”, 0);
  • break;
    }
  • r = genrand_real(&rnd->mt);
  • if (argc) r *= max;
  • return add_to_begin(beg, rb_float_new®);
  • else {
  • NUM2LONG(vmax);
  • }
  • if (NIL_P(v)) rb_raise(rb_eArgError, “invalid argument”);
  • return add_to_begin(beg, v);
    }

@@ -1020,5 +1107,5 @@ rb_f_rand(int argc, VALUE *argv, VALUE o
if (NIL_P(vmax)) goto zero_arg;
vmax = rb_to_int(vmax);

  • if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax))) {
  • if (vmax == INT2FIX(0) || NIL_P(r = rand_int(mt, vmax, 0))) {
    zero_arg:
    return DBL2NUM(genrand_real(mt));
    @@ -1059,7 +1146,6 @@ Init_Random(void)
    rb_define_alloc_func(rb_cRandom, random_alloc);
    rb_define_method(rb_cRandom, “initialize”, random_init, -1);
  • rb_define_method(rb_cRandom, “int”, random_int, 1);
  • rb_define_method(rb_cRandom, “rand”, random_rand, -1);
    rb_define_method(rb_cRandom, “bytes”, random_bytes, 1);
  • rb_define_method(rb_cRandom, “float”, random_float, -1);
    rb_define_method(rb_cRandom, “seed”, random_get_seed, 0);
    rb_define_method(rb_cRandom, “initialize_copy”, random_copy, 1);
    Index: test/ruby/test_rand.rb
    ===================================================================
    — test/ruby/test_rand.rb (revision 24648)
    +++ test/ruby/test_rand.rb (working copy)
    @@ -11,12 +11,12 @@ class TestRand < Test::Unit::TestCase
    assert_equal(w, rand(m))
    rnds.each do |rnd|
  •    assert_equal(w, rnd.int(m))
    
  •    assert_equal(w, rnd.rand(m))
     end
     rnds2.each do |rnd|
    
  •    r=rnd.int(i...(m+i))
    
  •    r=rnd.rand(i...(m+i))
       assert_equal(w+i, r)
     end
     rnds3.each do |rnd|
    
  •    r=rnd.int(i..(m+i-1))
    
  •    r=rnd.rand(i..(m+i-1))
       assert_equal(w+i, r)
     end
    

@@ -111,14 +111,12 @@ class TestRand < Test::Unit::TestCase
end

  • def test_neg_0x10000000000
  • def test_0x10000000000
    ws = %w(455570294424 1073054410371 790795084744 2445173525
    1088503892627)
    assert_random_int(ws, 0x10000000000, 3)
  • assert_random_int(ws, -0x10000000000, 3)
    end

  • def test_neg_0x10000

  • def test_0x10000
    ws = %w(2732 43567 42613 52416 45891)
    assert_random_int(ws, 0x10000)
  • assert_random_int(ws, -0x10000)
    end

@@ -127,17 +125,16 @@ class TestRand < Test::Unit::TestCase
rnd = Random.new(0)
assert_equal(44, rand(100.0))

  • assert_equal(44, rnd.int(100.0))
  • assert_equal(44, rnd.rand(100))
    assert_equal(1245085576965981900420779258691, rand((2**100).to_f))
  • assert_equal(1245085576965981900420779258691,
    rnd.int((2**100).to_f))
  • assert_equal(1245085576965981900420779258691, rnd.rand(2100))
    assert_equal(914679880601515615685077935113, rand(-(2
    100).to_f))
  • assert_equal(914679880601515615685077935113,
    rnd.int(-(2**100).to_f))

    srand(0)
    rnd = Random.new(0)
    assert_equal(997707939797331598305742933184, rand(2**100))

  • assert_equal(997707939797331598305742933184, rnd.int(2**100))

  • assert_equal(997707939797331598305742933184, rnd.rand(2100))
    assert_in_delta(0.602763376071644, rand((2
    100).coerce(0).first),
    0.000000000000001)
  • assert_equal(0, rnd.int((2**100).coerce(0).first))
  • assert_raise(ArgumentError) {rnd.rand((2**100).coerce(0).first)}

    srand(0)
    @@ -145,5 +142,5 @@ class TestRand < Test::Unit::TestCase
    assert_in_delta(0.548813503927325, rand(nil),
    0.000000000000001)

  • assert_in_delta(0.548813503927325, rnd.float(),
  • assert_in_delta(0.548813503927325, rnd.rand(),
    0.000000000000001)
    srand(0)
    @@ -152,9 +149,9 @@ class TestRand < Test::Unit::TestCase
    def o.to_int; 100; end
    assert_equal(44, rand(o))
  • assert_equal(44, rnd.int(o))
  • assert_equal(44, rnd.rand(o))
    assert_equal(47, rand(o))
  • assert_equal(47, rnd.int(o))
  • assert_equal(47, rnd.rand(o))
    assert_equal(64, rand(o))
  • assert_equal(64, rnd.int(o))
  • assert_equal(64, rnd.rand(o))
    end

@@ -162,5 +159,5 @@ class TestRand < Test::Unit::TestCase
srand
assert_kind_of(Integer, rand(2))

  • assert_kind_of(Integer, Random.new.int(2))
  • assert_kind_of(Integer, Random.new.rand(2))

    srand(2**100)
    @@ -168,5 +165,5 @@ class TestRand < Test::Unit::TestCase
    %w(3258412053).each {|w|
    assert_equal(w.to_i, rand(0x100000000))

  •  assert_equal(w.to_i, rnd.int(0x100000000))
    
  •  assert_equal(w.to_i, rnd.rand(0x100000000))
    
    }
    end
    @@ -184,9 +181,9 @@ class TestRand < Test::Unit::TestCase
    r = Random.new(0)
    %w(2357136044 2546248239 3071714933).each do |w|
  •  assert_equal(w.to_i, r.int(0x100000000))
    
  •  assert_equal(w.to_i, r.rand(0x100000000))
    
    end
    GC.start
    %w(3626093760 2588848963 3684848379).each do |w|
  •  assert_equal(w.to_i, r.int(0x100000000))
    
  •  assert_equal(w.to_i, r.rand(0x100000000))
    
    end
    end
    @@ -194,9 +191,9 @@ class TestRand < Test::Unit::TestCase
    def test_random_type_error
    assert_raise(TypeError) { Random.new(Object.new) }
  • assert_raise(TypeError) { Random.new(0).int(Object.new) }
  • assert_raise(TypeError) { Random.new(0).rand(Object.new) }
    end

def test_random_argument_error

  • assert_raise(ArgumentError) { Random.new(0).float(0, 0) }
  • assert_raise(ArgumentError) { Random.new(0).rand(0, 0) }
    end

@@ -211,15 +208,15 @@ class TestRand < Test::Unit::TestCase
r2 = r1.dup
%w(2357136044 2546248239 3071714933).each do |w|

  •  assert_equal(w.to_i, r1.int(0x100000000))
    
  •  assert_equal(w.to_i, r1.rand(0x100000000))
    
    end
    %w(2357136044 2546248239 3071714933).each do |w|
  •  assert_equal(w.to_i, r2.int(0x100000000))
    
  •  assert_equal(w.to_i, r2.rand(0x100000000))
    
    end
    r2 = r1.dup
    %w(3626093760 2588848963 3684848379).each do |w|
  •  assert_equal(w.to_i, r1.int(0x100000000))
    
  •  assert_equal(w.to_i, r1.rand(0x100000000))
    
    end
    %w(3626093760 2588848963 3684848379).each do |w|
  •  assert_equal(w.to_i, r2.int(0x100000000))
    
  •  assert_equal(w.to_i, r2.rand(0x100000000))
    
    end
    end
    @@ -310,5 +307,5 @@ END
    assert_equal(state, r.instance_eval { state })
    assert_equal(state, Random.instance_eval { state })
  • r.int(0x100)
  • r.rand(0x100)
    assert_equal(state, r.instance_eval { state })
    end
    @@ -317,7 +314,7 @@ END
    r = Random.new(0)
    assert_equal(1, r.instance_eval { left })
  • r.int(0x100)
  • r.rand(0x100)
    assert_equal(624, r.instance_eval { left })
  • r.int(0x100)
  • r.rand(0x100)
    assert_equal(623, r.instance_eval { left })
    srand(0)
    @@ -338,27 +335,26 @@ END
    def test_random_range
    r = Random.new(0)
  • %w(9 5 8).each {|w| assert_equal(w.to_i, r.int(5…9)) }
  • %w(-237 731 383).each {|w| assert_equal(w.to_i, r.int(-1000…1000))
    }
  • %w(9 5 8).each {|w| assert_equal(w.to_i, r.rand(5…9)) }
  • %w(-237 731 383).each {|w| assert_equal(w.to_i,
    r.rand(-1000…1000)) }
    %w(1267650600228229401496703205382
    1267650600228229401496703205384
    1267650600228229401496703205383).each do |w|
  •  assert_equal(w.to_i, r.int(2**100+5..2**100+9))
    
  •  assert_equal(w.to_i, r.rand(2**100+5..2**100+9))
    
    end
  • assert_equal(3, r.int(3.1…4), ‘[ruby-core:24679]’)
  • v = r.rand(3.1…4)
  • assert_instance_of(Float, v, ‘[ruby-core:24679]’)
  • assert_includes(3.1…4, v)
    end

def test_random_float
r = Random.new(0)

  • assert_in_delta(0.5488135039273248, r.float, 0.0001)
  • assert_in_delta(0.7151893663724195, r.float, 0.0001)
  • assert_in_delta(0.6027633760716439, r.float, 0.0001)
  • assert_in_delta(1.0897663659937937, r.float(2), 0.0001)
  • assert_in_delta(5.3704626067153264e+29, r.float(2100), 1025)
  • assert_in_delta(0.5488135039273248, r.rand, 0.0001)
  • assert_in_delta(0.7151893663724195, r.rand, 0.0001)
  • assert_in_delta(0.6027633760716439, r.rand, 0.0001)
  • assert_in_delta(1.0897663659937937, r.rand(2.0), 0.0001)
  • assert_in_delta(5.3704626067153264e+29, r.rand((2100).to_f),
    10
    25)
  • assert_raise(Errno::EDOM, Errno::ERANGE) { r.float(1.0 / 0.0) }
  • assert_raise(Errno::EDOM, Errno::ERANGE) { r.float(0.0 / 0.0) }
  • is this intentional?

  • assert_raise(TypeError) { r.float(1…2) }
  • assert_raise(Errno::EDOM, Errno::ERANGE) { r.rand(1.0 / 0.0) }
  • assert_raise(Errno::EDOM, Errno::ERANGE) { r.rand(0.0 / 0.0) }
    end

@@ -369,7 +365,7 @@ END
r1 = r.dup
r2 = r.dup

  • r1.int(0x100)
  • r1.rand(0x100)
    assert(r1 != r2)
  • r2.int(0x100)
  • r2.rand(0x100)
    assert(r1 == r2)
    end

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39158] Random#rand”
on Tue, 25 Aug 2009 18:23:11 +0900, Nobuyoshi N.
[email protected] writes:

|e$B:#$Ne(Btrunke$B$K$O!“;n83E*$Ke(BRandome$B%/%i%9$,$”$j$^$9!#$3$l$K$Oe(Binte$B$He(B
|floate$B$H$$$&%a%=%C%I$,$"$j$^$9$,!"e(BKernel#rande$B$H$N8_49@-$K7g$1$F$$e(B
|e$B$?$j!“e(BRangee$B$KBP$9$kF0:n$,$o$+$j$K$/$+$C$?$j$7$^$9!#$=$3$Ge(B
|Random#rande$B$KE}9g$7$?$$$H;W$&$N$G$9$,!”$$$+$,$G$7$g$&$+!#e(B

e$B$$$$$s$8$c$J$$$G$7$g$&$+!#E}9g$9$k$H8@$&$3$H$Oe(Binte$B$He(Bfloate$B$O:oe(B
e$B=|$H$$$&$3$H$G$7$g$&$+!#e(B

e$B@>;3OB9-$G$9!#e(B

At Tue, 25 Aug 2009 18:23:11 +0900,
Nobuyoshi N. wrote:

r = Random.new
r.rand #=> a float in 0.0…1.0
r.rand(max_num) #=> a number in 0.0…max_num
r.rand(range) #=> a number in range

e$B0z?t$,M?$($i$l$?>l9g$O7k2L$N%/%i%9$O0z?t$N%/%i%9$K=>$$$^$9!#e(B
Rangee$B$N>l9g$ON>C<$NCM$N:9$r;H$$$^$9!#e(B

Random#rand(1) e$B$He(B Random#rand(0…1)
e$B$N5sF0$,0c$&$N$O0U?^$7$?5sF0$G$7$g$&$+e(B?
e$B%(%i!<%a%C%;!<%8$,!Ve(Binvalid
argumente$B!W$@$1$J$N$b$o$+$j$K$/$$$h$&$Ke(B
e$B;W$$$^$9!#e(B

% ruby-trunk -e ‘p Random.new.rand(1)’
0
% ruby-trunk -e ‘p Random.new.rand(0…1)’
-e:1:in rand': invalid argument (ArgumentError) from -e:1:in
%

e$B0J2<$N$h$&$KJQ99$9$k$HF1$85sF0$K$J$j$^$7$?!#e(B

diff --git a/random.c b/random.c
index 3b5729f…9bd2c48 100644
— a/random.c
+++ b/random.c
@@ -1016,7 +1016,7 @@ random_rand(int argc, VALUE *argv, VALUE obj)
v = Qnil;
if (FIXNUM_P(vmax)) {
fixnum:

  • if ((max = FIX2LONG(vmax) - excl) > 0) {
  • if ((max = FIX2LONG(vmax) - excl) >= 0) {
    unsigned long r = limited_rand(&rnd->mt, (unsigned long)max);
    v = ULONG2NUM®;
    }