Согласие на обработку персональных данных.



04.09.2017
Новая задача Программа вычисления суммы.

03.09.2017
Новое видео Стековый калькулятор и обратная польская запись.

26.08.2017
Новая статья Версии Делфи.

23.08.2017
Новая статья Для кого пишется программа.

13.08.2017
Новая статья Стандарт C++: общие сведения.

Раздел: Стандартные функции Паскаля

Random и Randomize

Как стать программистом 2.0 Как стать программистом 2.0

Эта книга для тех, кто хочет стать программистом. На самом деле хочет, а не просто мечтает. И хочет именно стать программистом с большой буквы, а не просто научиться кулебякать какие-то примитивные программки… Подробнее...

Функция Random генерирует и возвращает случайное число. Синтаксис функции следующий:

function Random(L: LongInt) : LongInt;

function Random(L: Int64) : Int64;

function Random : extended;

Функция возвращает случайное число большее или равное 0 и строго меньше L (то есть L не входит в диапазон возвращаемых значений). Если параметр опущен (последний вариант из трёх приведённых выше), то возвращается вещественное число между 0 и 1 (0 включительно, 1 не входит в диапазон возвращаемых значений).

Математически это можно записать так:

0 <= Random < L, если L передаётся
0 <= Random < 1, если L опущен

ПРИМЕЧАНИЕ
FreePascal использует в процедуре Random имитацию случайностей Мерсенна Твистера. Эта реализация имеет большее статистическое распределение, чем, например, алгоритм Линейного Конгруэнтного генератора, но работает значительно медленнее, чем последний. Если скорость выполнения программы критична, то должны быть рассмотрены альтернативные генераторы случайных чисел.

Процедура Randomize в Паскале запускает генератор случайных чисел. Синтаксис:

procedure Randomize;

Процедура Randomize инициализирует генератор случайных чисел FreePascal, задавая значение переменной Randseed, вычисленное с помощью системных часов.

Как запустить генератор случайных чисел в Паскале

Пример программы, где используются разные варианты получения случайных чисел, приведён ниже:

program funcrand;

var x : integer;
    z : real;

begin
  Randomize;          //Запустить генератор случайных чисел
  x := Random(100);   //х - случайное число от 0 до 99
  WriteLn(x);

  z := Random(100);   //х - случайное число от 0 до 99
  WriteLn(z:0:4);

  z := Random;        //х - случайное число от 0 до 0,9999...
  WriteLn(z:0:4);

  ReadLn;
end.

ВАЖНО!
Перед использованием функции Random надо обязательно вызвать процедуру Randomize, чтобы запустить генератор случайных чисел. Иначе функция Random будет возвращать НЕ случайное число.

Процедура Randomize вызывается ТОЛЬКО ОДИН РАЗ в начале программы. Типичная ошибка новичков заключается в том, что они вызывают Randomize перед каждым вызовом Random. Этого делать не надо.

Что такое Randseed

Давайте сначала попробуем не использовать процедуру Randomize. Например, так:

x := Random(100);   
WriteLn(x);

z := Random(100);   
WriteLn(z:0:4);

В этом примере функция Random будет возвращать какое-то значение, но оно НЕ будет случайным числом. Сколько бы раз вы не запускали программу, она всегда будет выводить одинаковые числа.

В моём случае это были числа 54 и 59. В вашем случае это могут быть другие числа, но суть не в этом, а в том, что они будут всегда одинаковыми.

Теперь попробуем сделать так:

Randseed := 500;

x := Random(100);   //х - случайное число от 0 до 99
WriteLn(x);

z := Random(100);   //х - случайное число от 0 до 99
WriteLn(z:0:4);

Теперь числа будут другими. В моём случае 69 и 7. Правда, они тоже не будут изменяться, то есть не будут случайными.

Однако эти числа изменились. Потому что мы изменили значение глобальной переменной Randseed.

Переменная Randseed - это глобальная предопределённая переменная в FreePascal. Она также есть и в Делфи. Так что всё сказанное будет справедливо и для Делфи.

Эта переменная задаёт начальное значение для генератора случайных чисел. Опираясь на это значение функция Random генерирует случайное число. Но, если значение переменной Randseed будет всегда одинаковым, то никаких случайных чисел мы не получим.

Поэтому при запуске программы надо хотя бы один раз вызвать процедуру Randomize, которая устанавливает начальное значение переменной Randseed, получая системное время и из этих данных формируя значение для переменной Randseed.

Так как программа запускается в какое-то случайное время, то и значение переменной Randseed будет случайным. А, следовательно, и функция Random будет возвращать случайные значения.

Давайте попробуем написать свою процедуру Randomize. Она может быть, например, такой:

//**************************************
// Процедура, которая имитирует работу 
// стандартной процедуры Randomize
//***************************************
procedure MyRandomize;
var h, m, s, ms : Word;
begin
  DecodeTime(Now, h, m, s, ms);
  Randseed := ms;
end;

Я не буду в подробностях разъяснять работу процедуры DecodeTime. Скажу только, то она возвращает, час, минуту, секунду и миллисекунду текущего времени компьютера. Мы используем миллисекунду, значение которой и присваиваем переменной Randseed.

Можете попробовать использовать эту процедуру вместо стандартной процедуры Randomize и убедиться, что функция Random возвращает случайные значения. Не забудьте подключить к программе модуль SysUtils, в котором объявлена процедура DecodeTime, иначе программа не откомпилируется.

ПРИМЕЧАНИЕ
Исходя из того, что процедура Randomize задаёт начальное значение переменной Randseed на основе текущего времени компьютера, можно предположить, что, например, если запустить программу сегодня в 12:00:00 и завтра в это же время, то функция Random вернёт одинаковые числа.

К сожалению, проверить это очень трудно, так как запустить программу в одно и то же время с точностью до миллисекунды будет практически невозможно.


Директивы компилятора Директивы компилятора
Как это ни странно, но даже многие опытные программисты не используют директивы компилятора, считая их чем-то ненужным и бесполезным. А между тем, директивы компилятора - это очень классная штука. Если их умело применять в своих программах, то можно существенно сократить время на разработку и уменьшить количество рутинных операций. Подробнее...
Инфо-МАСТЕР ®
Все права защищены ©
e-mail: mail@info-master.su

Яндекс.Метрика