Spec-Zone.ru › Ruby 4.0

класс Random

Random предоставляет интерфейс к генератору псевдослучайных чисел Ruby, или PRNG. PRNG создает детерминированную последовательность битов, приближенную к истинной случайности. Последовательность может быть представлена целыми числами, числами с плавающей точкой или двоичными строками.

Генератор можно инициализировать системным или заданным пользователем начальным значением с помощью Random.srand.

Метод класса Random.rand предоставляет базовую функциональность Kernel.rand и лучше обрабатывает числа с плавающей точкой. Оба метода являются интерфейсами к системному PRNG Ruby.

Random.new создаст новый PRNG с состоянием, независимым от системного PRNG Ruby, что позволит одновременно использовать несколько генераторов с разными начальными значениями или позициями в последовательности. Объекты Random можно сериализовать с помощью Marshal, что позволяет сохранять и продолжать последовательности.

В настоящее время PRNG реализованы как модифицированный вихрь Мерсенна с периодом 2**19937-1. Поскольку этот алгоритм не предназначен для криптографического использования, в целях безопасности необходимо использовать SecureRandom, а не этот PRNG.

См. также модуль Random::Formatter, добавляющий удобные методы для генерации различных видов случайных данных.

Публичные методы класса

bytes(size) → string Показать исходный код
static VALUE
random_s_bytes(VALUE obj, VALUE len)
{
    rb_random_t *rnd = default_rand_start();
    return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
}

Возвращает случайную двоичную строку. Аргумент size задает длину возвращаемой строки.

new(seed = Random.new_seed) → prng Показать исходный код
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) {
        RB_OBJ_WRITE(obj, &rnd->seed, rand_init_default(rng, rnd));
    }
    else {
        RB_OBJ_WRITE(obj, &rnd->seed, rand_init(rng, rnd, rb_to_int(argv[0])));
    }
    return obj;
}

Создает новый PRNG, используя seed для установки начального состояния. Если seed не указан, генератор инициализируется с помощью Random.new_seed.

Подробнее об использовании начальных значений см. в разделе Random.srand.

new_seed → integer Показать исходный код
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
rand → float Показать исходный код
rand(max) → number
rand(range) → number
static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
    VALUE v = rand_random(argc, argv, Qnil, default_rand_start());
    check_random_number(v, argv);
    return v;
}

Возвращает случайное число, используя системный PRNG Ruby.

См. также Random#rand.

seed → integer Показать исходный код
static VALUE
random_s_seed(VALUE obj)
{
    rb_random_mt_t *rnd = default_mt();
    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
srand(number = Random.new_seed) → old_seed Показать исходный код
static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
    VALUE seed, old;
    rb_random_mt_t *r = default_mt();

    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]
urandom(size) → string Показать исходный код
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 году в справочной странице Linux random(7) было сказано: «ни одна из доступных сегодня криптографических примитивных функций не может гарантировать более 256 бит безопасности». Поэтому передача этому методу значения size > 32 может быть сомнительной.

Random.urandom(8)  #=> "\x78\x41\xBA\xAF\x7D\xEA\xD8\xEA"

Публичные методы экземпляра

prng1 == prng2 → true or false Показать исходный код
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
bytes(size) → string Показать исходный код
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
rand → float Показать исходный код
rand(max) → number
rand(range) → number
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. Обратите внимание, что поведение отличается от Kernel.rand.

prng.rand(1.5)  # => 1.4600282860034115
rand(1.5)       # => 0

Если 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

Для начального и конечного значений диапазона должны быть определены методы subtract (-) и add (+); иначе rand вызовет исключение ArgumentError.

seed → integer Показать исходный код
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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API