Насколько надежна функция Random в Delphi

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

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


person Daisetsu    schedule 15.10.2010    source источник
comment
Необходимость запуска функции рандомизатора вовсе не редкость — вы должны сделать то же самое с твистером Мерсенна.   -  person Michael Madsen    schedule 16.10.2010
comment
И возможность запуска случайной функции часто является большим преимуществом. Используя одно и то же семя, вы можете дублировать свои результаты, что может очень помочь, например, при отладке.   -  person Svein Bringsli    schedule 16.10.2010
comment
Отличное обсуждение этой темы содержится в главе 6 книги Джулиана Бакнелла Томы Дельфи: Алгоритмы и структуры данных (www.boyet.com).   -  person MikeJ-UK    schedule 18.10.2010


Ответы (9)


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

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

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

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

person PhiS    schedule 16.10.2010

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

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

person Barry Kelly    schedule 16.10.2010

альтернативный текст

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

person Mick    schedule 16.10.2010
comment
Мне нравится юмор. Но это должно быть CW! - person Andreas Rejbrand; 16.10.2010
comment
Нет, нет CW, это прекрасно иллюстрирует, что то, что мы можем воспринимать как неслучайное, на самом деле может быть совершенно случайным. В конце концов, случайность — это не отсутствие закономерности... - person Marjan Venema; 16.10.2010
comment
Каждый раз, когда вы чувствуете склонность поставить «Я не мог устоять» в своем ответе, вы должны быть склонны сделать это CW. Это вопрос степени, но в данном случае прямого ответа на ОП не было. - person Argalatyr; 16.10.2010
comment
Я в порядке с людьми, которые голосуют против этого. У меня нет возможности сделать это вики сообщества. Голосуйте за / против, я действительно не против ... Я не пытаюсь играть в систему репутации SO. - person Mick; 17.10.2010

Если вы ищете способ гарантировать уникальность случайных чисел с самым быстрым временем выполнения, About.com создал задачу на Самый быстрый генератор уникальных случайных чисел и Реализация Патрика ван Логхема была выбрана победителем.

person Vantomex    schedule 16.10.2010

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

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

person James McLeod    schedule 16.10.2010


С веб-сайта Эмбаркадеро:

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

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

person dbasnett    schedule 17.10.2010

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

Randseed:=int32(Randseed*$08088405)+1
result:=Randseed*Range shr 32

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

person CodesInChaos    schedule 17.10.2010

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

StrToInt(copy(FloatToStr(Random),4,1))

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

person DejanR    schedule 11.09.2012
comment
Рекомендуемый вызов для генерации случайного целого числа в диапазоне от 0 до 9 — random(10). Использование floattostr разумно, но приведенное выражение иногда не работает. Учтите: рандом := -1498392781; X := StrToInt(copy(FloatToStr(Random),4,1)); В этом случае random вернет ровно 0,5, floattostr вернет 0,5, так как четвертого символа нет, copy вернет пустую строку, а StrToInt завершится ошибкой с исключением. - person David Dubois; 19.09.2012
comment
Идея заключалась в том, чтобы привести пример с большей дисперсией (см. ссылку). Таким образом, вы можете свободно улучшать этот алгоритм в соответствии с вашими потребностями. . - person DejanR; 20.09.2012