Функция srand() в Perl

В языке программирования Perl есть встроенная функция srand().

Эта функция используется для установки или для получения номера последовательности, числовые значения из которой возвращает функция rand().

Чаще всего функция srand() используется в тестах, чтобы при каждом запуске теста функция rand() возвращала одни и те же значения.

Вот пример кода:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;
use feature qw(say);

srand(16);

say int(rand(10));
say int(rand(10));
say int(rand(10));
say int(rand(10));
say int(rand(10));

Результат работы программы — это всегда одни и те же 5 цифр:

1
0
9
3
3

Программа использует int(rand(10)) для того чтобы получить случайное число от 0 (включительно), до 9 (включительно).

В коде есть вызов srand(16);. Этот вызов устанавливает что функция rand() должна возвращать числа из псевдослучайной последовательности номер 16. Поэтому каждый запуск этой программы приводит к одному и тому же результату. Если бы в этой программе не было вызова функции srand(), то разные запуски программы могут вернуть разные значения.

Аргументы

Функцию srand() можно использовать без аргументов, либо передать ей ровно один аргумент.

В том случае если передать ей больше чем один аргумент, то будет ошибка:

Too many arguments for srand at script.pl line 3, near "2)"
Execution of script.pl aborted due to compilation errors.

Функция не использует дефолтную переменную $_. Если есть необходимость ее использовать, то ее нужно явно передать в функцию srand($_);.

Функция ожидает получить число в качестве значения аргумента. Если функция получает не число, то она приводит его к числу.

Функция отбрасывает дробную часть и знак. srand(-2.9) — это то же самое что и srand(2). Вот пример кода, который это показывает:

▶ Run
#!/usr/bin/perl

use strict;
use warnings;

foreach my $n (-2, 2, 2.1, 2.9, -2.1, -2.9) {
    my $real_n = srand($n);
    my @arr;
    foreach (1..5) {
        push @arr, int(rand(10));
    }
    printf "%4s  %s  (%s)\n", $n, $real_n, join(', ', @arr);
}

Возвращаемое значение

Начиная с версии Perl 5.14 функция srand() всегда возвращает число от 1 до 4294967296, либо строку 0 but true. Это число — это номер последовательности, которая используется в функции rand().

Если функцию srand() вызвать без аргументов, то она вернет номер последовательности, который был установлен автоматически.

Если же функцию вызвать с аргументом, то она вернет то значение номера последовательности, которое было установлено из этого аргумента:

▶ Run
#!/usr/bin/perl

use feature qw(say);

say srand(1573); # 1573
say srand(-2.9); # 2

Интересно что для последовательности с номером 0 функция возвращает строку 0 but true:

▶ Run
#!/usr/bin/perl

print srand(0);

До версии Perl 5.14 функция srand() всегда возвращала число 1.

Официальная документация

Вот вывод команды perldoc -f srand:

    srand EXPR
    srand   Sets and returns the random number seed for the "rand" operator.

            The point of the function is to "seed" the "rand" function so
            that "rand" can produce a different sequence each time you run
            your program. When called with a parameter, "srand" uses that
            for the seed; otherwise it (semi-)randomly chooses a seed. In
            either case, starting with Perl 5.14, it returns the seed. To
            signal that your code will work *only* on Perls of a recent
            vintage:

                use 5.014;  # so srand returns the seed

            If "srand" is not called explicitly, it is called implicitly
            without a parameter at the first use of the "rand" operator.
            However, there are a few situations where programs are likely to
            want to call "srand". One is for generating predictable results,
            generally for testing or debugging. There, you use
            "srand($seed)", with the same $seed each time. Another case is
            that you may want to call "srand" after a "fork" to avoid child
            processes sharing the same seed value as the parent (and
            consequently each other).

            Do not call "srand()" (i.e., without an argument) more than once
            per process. The internal state of the random number generator
            should contain more entropy than can be provided by any seed, so
            calling "srand" again actually *loses* randomness.

            Most implementations of "srand" take an integer and will
            silently truncate decimal numbers. This means "srand(42)" will
            usually produce the same results as "srand(42.1)". To be safe,
            always pass "srand" an integer.

            A typical use of the returned seed is for a test program which
            has too many combinations to test comprehensively in the time
            available to it each run. It can test a random subset each time,
            and should there be a failure, log the seed used for that run so
            that it can later be used to reproduce the same results.

            "rand" is not cryptographically secure. You should not rely on
            it in security-sensitive situations. As of this writing, a
            number of third-party CPAN modules offer random number
            generators intended by their authors to be cryptographically
            secure, including: Data::Entropy, Crypt::Random,
            Math::Random::Secure, and Math::TrulyRandom.

Связанные темы

Другие статьи