Как сделать рандом в delphi

Обновлено: 04.07.2024

Я пишу программу, которая пишет статистические тесты на Delphi (должен быть Delphi), и я слышал, что функция Random несколько странная. Вы должны вызвать randomize, чтобы рандомизировать начальное число случайной функции при запуске программы.

Мне интересно, является ли случайная функция (после вызова randomize) достаточно случайной для статистических тестов или нужен твистер Мерсенна? Кто-нибудь имеет представление о реальной реализации random, которая может сказать мне, насколько это важно?

Достаточно ли надежна Random для ваших статистических тестов, зависит от контекста, в котором вы собираетесь его использовать.

Сказав это, я написал несколько фрагментов кода Delphi, которые должны вести правильную статистику, и использовал Random , например. для получения различных нулевых распределений, псевдорепликации данных и повторной выборки. До сих пор я не сталкивался ни с одним случаем в своем собственном коде, где Random дало бы смещенные или ненадежные результаты или результаты, которые имели бы исключил его использование для предполагаемого статистического теста. Но то, что справедливо для моего кода, не обязательно должно относиться к вашему.

Если вы сомневаетесь, вы, конечно, можете статистически анализировать результаты вызовов Random (например, в R, SPSS и т. д.) и проверьте, не нарушает ли распределение результатов требования к распределению для вашего конкретного статистического теста (тестов). [Если вы настоящий ученый, это то, что вы должны делать в любом случае.]

Если вам нужны другие PRNG, например, библиотека TPMath содержит некоторые из них. (Для более сложных вещей есть также возможность вызова сложных статистических функций из R через Delphi.)

PRNG Delphi, как и почти все PRNG на языке программирования RTL, представляет собой линейный конгруэнтный генератор . /р>

Это достаточно хорошо для большинства мелких вещей, но есть вещи, которые нужно остерегаться. В частности, следите за битами младших разрядов: шаблон умножения и сложения означает, что биты младших разрядов совсем не случайны. Но это обычно относится только к большим 32-битным значениям, которые извлекаются, а затем усекаются с помощью mod или аналогичного. Использование Random(10) для извлечения значения между 0 и 9 внутренне использует умножение во всем 32-битном диапазоне, а не mod операция.

Random без повтора чисел

Random без повтора чисел

Еще в прошлом году мы познакомились со стандартным оператором рандом, отвечающим за генерацию случайных чисел. Оператор очень полезный, так как нам не приходится лично вбивать данные с клавиатуры или подключать файлы с массивами данных. Однако у рандома как оператора есть один маленький минус: так как числа берутся случайно и ограничение имеют только в диапазоне, то они могут повторятся. Конечно, кого-то это устраивает, однако для некоторых это проблема, которую приходится решать самому. Совсем недавно меня попросили написать как можно более простую программу, в которой random выводил бы числа так, чтобы ни одно число не повторялось. На самом деле сделать это просто. Как мы знаем, оператор random выводит случайные числа и они могут повторяться.

Особенно это видно при задании узкого диапазона, например если вывести 10 элементов массива, заполнив их случайными числами в диапазоне от 0 до 9, то среди них почти всегда есть повторы. Ниже код реализации.

const
n = 10;

var
m: array [1..n] of integer;
i:integer;

begin
randomize;
for i := 1 to n do
begin
z: m[i] := random(1, 10);
write(m[i]);
end;
end.

Каков наш алгоритм, позволяющий убрать повтор чисел ? Для того,чтобы числа не повторялись, нам достаточно сделать своего рода фильтр ,который из всех случайных чисел будет брать только те,которых еще не было. Объясняю на примере массива. Смотрим последовательность.

Шаг 1.Заполняем первый элемент массива

Шаг 2.Заполняем второй элемент

Подшаг 1. Сверяем его с первым.

а) Если элементы разные, то переходим к следующему шагу.
б) Если они одинаковы ,то заполняем второй элемент еще раз до тех пор, пока они не будут неравными.

Шаг 3. Заполняем третий элемент.

Подшаг 1. Сверяем его с первым.

а) Если элементы разные, то переходим к следующему подшагу.
б) Если они одинаковы, то заполняем третий элемент еще раз до тех пор, пока они не будут неравными.

Подшаг 2. Сверяем его со вторым.

а) Если элементы разные, то переходим к следующему шагу.
б) Если они одинаковы, то заполняем третий элемент еще раз до тех пор, пока они не будут неравными.

Random без повтора чисел

Random без повтора чисел

На картинке изображен момент, когда шаг равен 3 и происходит сначала сравнение третьего элемента и первого, а затем третьего и второго. И таким вот образом алгоритм повторяется от первого щага до десятого. Каждый раз, когда мы делаем i шагов, мы делаем i-1 подшагов.

А теперь весь алгоритм. Для алгоритма был использован оператор goto. О нем я уже упоминал в статье выход из цикла. Итак код алгоритма

randomize;
for i := 1 to n do
begin
z: m[i] := random(1, 10);
for k := 1 to i — 1 do
if m[k] = m[i] then goto z;
end;

Полный код с выводом сгенерированных элементов массива на экран.

label z;
const
n = 10;

var
m: array [1..n] of integer;
i, k: integer;

begin
randomize;
for i := 1 to n do
begin
z: m[i] := random(1, 10);
for k := 1 to i — 1 do
if m[k] = m[i] then goto z;
end;

for i := 1 to n do
write(m[i]:3);
end.

Тот же код, но без использования метки.

const
n = 10;

var
m: array [1..n] of integer;
i, k: integer;

begin
randomize;
i := 0;
while i

Спасибо за статью ) Всегда с удовольствием читаю ваши посты

Не за что)
Для этого и создавался сайт
Жаль,что в последнее время много дел,из-за чего я не успеваю писать. Но это ненадолго.
Кстати, советую Вам подписаться ,если Вы еще не подписаны)

Группа: Гости
Публикаций: 0
Комментариев: 0

Евгения,
Здравствуйте,
Вообще мы пишем код для PascalABC и TurboPascal, просто есть некоторые вещи, которые необходимо дописывать, если Вы хотите запустить программу через TurboPascal. Например пустой readln в самом конце любой программы (для вывода результата на экран ) или тот же самый random в TurboPascal пишеться по-другому (подробнее в статье Оператор random ). Я проверил код в TurboPascal — все работает. Не могли бы Вы прислать скриншот программы ?

Я пишу программу, которая пишет статистические тесты в Delphi (должен быть Delphi), и я слышал, что функциональность Random несколько странная. Вы должны вызвать рандомизацию, чтобы рандомизировать семя случайной функции при запуске программы.

Мне интересно, является ли случайная функция (после рандомизации) случайным образом для статистических тестов или нужен Mersenne twister? Кто-нибудь имеет представление о случайной фактической реализации, которая может сказать мне, насколько это важно?

Delphi PRNG, как и почти все языки программирования RTL PRNG, является линейным конгруэнтным генератором.

Это достаточно хорошо для большинства мелких вещей, но есть вещи, на которые нужно следить. В частности, следите за младшими битами: шаблон умножения и добавления означает, что младшие разряды не очень случайны. Но это в целом относится только к большим 32-битным значениям, выведенным, а затем усеченным с mod или аналогичным. Использование Random(10) для вырезания значения между 0 и 9 внутренне использует умножение во всем 32-битном диапазоне, а не на операцию mod .

alt text

Я не мог сопротивляться.

Является ли Random достаточно надежным для ваших статистических тестов, будет зависеть от контекста, в котором вы собираетесь его использовать.

Сказав это, я написал несколько фрагментов кода Delphi, которые должны выполнять правильную статистику, и использовали Random , например. для получения различных нулевых распределений, псевдорепликаций данных и повторных попыток. До сих пор я не встречал ни одного случая в своем собственном коде, где Random приводило бы к предвзятым или ненадежным результатам или результатам, которые исключали бы его использование для предполагаемого статистического теста. Но то, что имеет место для моего кода, необязательно для вас.

Если вы сомневаетесь, вы можете, конечно, статистически проанализировать результаты вызовов Random (например, в R, SPSS и т.д.) и проверить, нарушает ли распределение результатов требования распределения для вашего конкретного статистического теста (ов), [Если вы хороший ученый, это то, что вы должны делать в любом случае.]

Если вам нужны другие PRNG - например, библиотека TPMath содержит некоторые. (Для более вовлекаемых вещей есть также возможность вызывать сложные статистические функции из R через Delphi.)

Если вы не покупаете какое-то относительно эзотерическое оборудование, наилучшим приближением к случайным числам, которые может предоставить компьютер, является полностью детерминированная псевдослучайная последовательность. В общем случае функция рандомизации использует некоторое относительно случайное значение (часто основанное на времени, но иногда на движениях мыши - я не знаю, что делает Delphi) в качестве семени, которое обеспечивает точку входа в псевдослучайную последовательность. Без этого вы в конечном итоге получите один и тот же набор случайных чисел в том же порядке каждый раз, что в первую очередь приведет к победе в использовании случайных чисел.

Хорошо, я понимаю, что это не отвечает на вопрос о надежности, но это должно дать вам некоторую уверенность в том, что требование назвать случайным образом является признаком хорошего генератора, а не плохого. Существует множество статистических тестов, которые показывают, насколько случайна последовательность чисел, и вполне вероятно, что генератор случайных чисел Delphi подходит для многих целей, поскольку это зрелый продукт.

Просто добавьте в пул возможностей - Windows предлагает ряд встроенных функций криптографии. Вероятно, для них также есть оболочка Delphi, если она по умолчанию не включена.

Среди этих функций также есть криптографически сильный генератор случайных чисел. Это, безусловно, лучшая случайность, которую вы получите в программном обеспечении, потому что она основывается на очень длинном списке факторов. Я не уверен, но я подозреваю, что он даже будет использовать генератор случайных чисел оборудования, если он у вас есть.

И если этого недостаточно, вы также можете попытаться зарегистрироваться в Quantum Random Bit Generator Service для некоторых ДЕЙСТВИТЕЛЬНОсильные > случайные значения.

С веб-сайта Embarcadero:

_lrand - функция генератора длинных случайных чисел. _rand использует мультипликативный конгруэнтный генератор случайных чисел с периодом 2 ^ 64 для возврата последовательных псевдослучайных чисел в диапазоне от 0 до 2 ^ 31 - 1.

Генератор повторно инициализируется вызовом srand со значением аргумента 1. Его можно установить в новую начальную точку, вызвав srand с заданным количеством семян.

Если они не изменили реализацию, так как я ее проанализировал (Delphi 4 IIRC), Delphi PRNG реализуется следующим образом:

(Псевдокод/​​предполагаем, что умножения находятся на сколь угодно больших целых числах)

Возврат случайного значения между 0..9

Примечание. Проверяйте длину FloatToStr (Random) перед использованием или используйте любую другую цифру из десятичной части.

Собственно возникла такая необходимость в одной из программ вытаскивать случайное слово из строки, самому писать было лень, гугление не принесло результатов, пришлось вспомнить былые годы и напрячь мозговые центры ))))
Ничего сложного нет, алгоритм прост, хотя я и не настаиваю на его универсальности и простоте, кому как, но на скорую руку написал следующее, в двух словах по алгоритму, в строке выдергиваем случайный символ, и если это не пробел, то увеличиваем номер символа пока не получаем пробел (банально )))), после удалем из строки все символы, начиная с первого, заканчивая пробелом, далее копируем в результат все, начиная с первого символа, заканчивая пробелом, номер символа которого мы получим из Pos(‘ ‘, str).

Хватит бесполезной болтовни, вот вам функция:

З.Ы. пипец накрутил с описанием алгоритма, надо было схемой зарисовать,ну ладно, может в следующий раз, а пока что, если что не ясно, не стесняемся, пишем

2 комментария . Оставить новый

Как я писал в статье, гавнокодил на скорую руку, поэтому не настаиваю на его универсальности, многих проверок не делал, т.к. исходный текст всегда содержал пробелы, но в целом согласен, добавить проверку на наличие пробела можно, например добавить условие, проверяющее, Pos(‘ ‘, str), чтобы не было равно нулю.

95% кода в интернете – говно. Случайно наткнулся на данную чудо-функцию. И вот какие соображения.
Чтобы выбрать именно СЛУЧАЙНОЕ слово из строки, надо для начала хотя бы знать количество этих слов. Что, если в строке вообще нет пробелов? Тогда функция отработает неправильно.
Далее, ищем пробел, удаляем всё до пробела, и затем:
Result:= Copy(Str, 1, Pos(‘ ‘, str)-1)
Занимательно. А что, если пробела в str не будет? Благо, Copy таки отработает. И слава Богу.

Читайте также: