класс Random
Random предоставляет интерфейс к генератору псевдослучайных чисел Ruby, или PRNG. PRNG генерирует детерминированную последовательность битов, приближенную к истинной случайности. Последовательность может быть представлена целыми числами, числами с плавающей точкой или двоичными строками.
Генератор можно инициализировать начальным значением, сгенерированным системой или заданным пользователем, с помощью Random.srand.
Метод класса Random.rand предоставляет базовую функциональность Kernel.rand и лучше обрабатывает значения с плавающей точкой. Оба метода являются интерфейсами к системному PRNG Ruby.
Random.new создаёт новый PRNG с состоянием, независимым от системного PRNG Ruby, что позволяет одновременно использовать несколько генераторов с разными начальными значениями или позициями в последовательности. Объекты Random можно сериализовать с помощью Marshal, что позволяет сохранять и возобновлять последовательности.
В настоящее время PRNG реализованы как модифицированный вихрь Мерсенна с периодом 2**19937-1. Поскольку этот алгоритм не предназначен для криптографического использования, в целях безопасности вместо этого PRNG необходимо использовать SecureRandom.
См. также модуль Random::Formatter, добавляющий удобные методы для генерации различных видов случайных данных.
Общедоступные методы класса
static VALUE
random_s_bytes(VALUE obj, VALUE len)
{
rb_random_t *rnd = rand_start(default_rand());
return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
} Возвращает случайную двоичную строку. Аргумент size задаёт длину возвращаемой строки.
static VALUE
random_init(int argc, VALUE *argv, VALUE obj)
{
rb_random_t *rnd = try_get_rnd(obj);
const rb_random_interface_t *rng = rb_rand_if(obj);
if (!rng) {
rb_raise(rb_eTypeError, "undefined random interface: %s",
RTYPEDDATA_TYPE(obj)->wrap_struct_name);
}
unsigned int major = rng->version.major;
unsigned int minor = rng->version.minor;
if (major != RUBY_RANDOM_INTERFACE_VERSION_MAJOR) {
rb_raise(rb_eTypeError, "Random interface version "
STRINGIZE(RUBY_RANDOM_INTERFACE_VERSION_MAJOR) "."
STRINGIZE(RUBY_RANDOM_INTERFACE_VERSION_MINOR) " "
"expected: %d.%d", major, minor);
}
argc = rb_check_arity(argc, 0, 1);
rb_check_frozen(obj);
if (argc == 0) {
rnd->seed = rand_init_default(rng, rnd);
}
else {
rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0]));
}
return obj;
} Создаёт новый PRNG, используя seed для установки начального состояния. Если seed не указан, генератор инициализируется с помощью Random.new_seed.
Дополнительные сведения об использовании начальных значений см. в описании Random.srand.
static VALUE
random_seed(VALUE _)
{
VALUE v;
with_random_seed(DEFAULT_SEED_CNT, 1, true) {
v = make_seed_value(seedbuf, DEFAULT_SEED_CNT);
}
return v;
} Возвращает произвольное начальное значение. Оно используется методом Random.new, если начальное значение не указано в качестве аргумента.
Random.new_seed #=> 115032730400174366788466674494640623225
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;
} Возвращает случайное число, используя системный PRNG Ruby.
См. также Random#rand.
static VALUE
random_s_seed(VALUE obj)
{
rb_random_mt_t *rnd = rand_mt_start(default_rand());
return rnd->base.seed;
} Возвращает начальное значение, использованное для инициализации системного PRNG Ruby. Его можно использовать позднее для инициализации другого генератора с тем же состоянием, чтобы он генерировал ту же последовательность чисел.
Random.seed #=> 1234 prng1 = Random.new(Random.seed) prng1.seed #=> 1234 prng1.rand(100) #=> 47 Random.seed #=> 1234 Random.rand(100) #=> 47
static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
rb_random_mt_t *r = rand_mt_start(default_rand());
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
}
else {
seed = rb_to_int(argv[0]);
}
old = r->base.seed;
rand_init(&random_mt_if, &r->base, seed);
r->base.seed = seed;
return old;
} Задаёт начальное значение системного генератора псевдослучайных чисел: number. Возвращается предыдущее начальное значение.
Если number не указан, генератор инициализируется с использованием источника энтропии, предоставляемого операционной системой, если он доступен (/dev/urandom в Unix-системах или криптографический провайдер RSA в Windows); затем полученное значение объединяется со временем, идентификатором процесса и порядковым номером.
srand можно использовать, чтобы обеспечить повторяемость последовательностей псевдослучайных чисел при разных запусках программы. Установка известного начального значения позволяет сделать поведение программ детерминированным во время тестирования.
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
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, TRUE))
rb_raise(rb_eRuntimeError, "failed to get urandom");
return buf;
} Возвращает строку, используя возможности платформы. Предполагается, что возвращаемое значение представляет собой криптографически стойкое псевдослучайное число в двоичной форме. Этот метод вызывает исключение RuntimeError, если предоставляемая платформой возможность не смогла подготовить результат.
В 2017 году в man-странице Linux random(7) было указано, что «ни один доступный сегодня криптографический примитив не может гарантировать более 256 бит безопасности». Поэтому передача в этот метод значения size > 32 может быть сомнительной.
Random.urandom(8) #=> "\x78\x41\xBA\xAF\x7D\xEA\xD8\xEA"
Общедоступные методы экземпляра
static VALUE
rand_mt_equal(VALUE self, VALUE other)
{
rb_random_mt_t *r1, *r2;
if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
r1 = get_rnd_mt(self);
r2 = get_rnd_mt(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->base.seed, r2->base.seed);
} Возвращает true, если два генератора имеют одинаковое внутреннее состояние, и false в противном случае. Эквивалентные генераторы возвращают одинаковую последовательность псевдослучайных чисел. Обычно два генератора имеют одинаковое состояние, только если они были инициализированы одним и тем же начальным значением
Random.new == Random.new # => false Random.new(1234) == Random.new(1234) # => true
и имеют одинаковую историю вызовов.
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_bytes(VALUE obj, VALUE len)
{
rb_random_t *rnd = try_get_rnd(obj);
return rand_bytes(rb_rand_if(obj), rnd, NUM2LONG(rb_to_int(len)));
} Возвращает случайную двоичную строку, содержащую size байт.
random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO" random_string.size # => 10
static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE v = rand_random(argc, argv, obj, try_get_rnd(obj));
check_random_number(v, argv);
return v;
} Если max — это Integer, rand возвращает случайное целое число, большее или равное нулю и меньшее max. В отличие от Kernel.rand, если max — отрицательное целое число или ноль, rand вызывает исключение ArgumentError.
prng = Random.new prng.rand(100) # => 42
Если max — это Float, rand возвращает случайное число с плавающей точкой в диапазоне от 0.0 до max, включая 0.0, но не включая max.
prng.rand(1.5) # => 1.4600282860034115
Если range — это Range, rand возвращает случайное число, для которого выполняется 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
Для начального и конечного значений диапазона должны быть определены методы вычитания (-) и сложения (+), иначе rand вызовет исключение ArgumentError.
static VALUE
random_get_seed(VALUE obj)
{
return get_rnd(obj)->seed;
} Возвращает начальное значение, использованное для инициализации генератора. Его можно использовать позднее для инициализации другого генератора с тем же состоянием, чтобы он генерировал ту же последовательность чисел.
prng1 = Random.new(1234) prng1.seed #=> 1234 prng1.rand(100) #=> 47 prng2 = Random.new(prng1.seed) prng2.rand(100) #=> 47
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.