Изобретение колеса: генератор случайных чисел

#c #algorithm #random #numbers #seed

#c #алгоритм #Случайный #числа #начальное

Вопрос:

Итак, я новичок в C и пытаюсь кое-чему научиться. Таким образом, я пытаюсь создать генератор случайных чисел (RNG или PRNG, если хотите). У меня есть базовые знания о ГСЧ, например, вы должны начать с начального значения, а затем отправить начальное значение с помощью алгоритма. Я застрял на том, как люди придумывают указанные алгоритмы.

Вот код, который мне нужен, чтобы получить начальное значение.

 int getSeed()
{
    time_t randSeed;
    randSeed = time(NULL);
    return randSeed;
}
  

Теперь я знаю, что в C есть готовые ГСЧ, но я хочу научиться не просто копировать работу других людей и пытаться разобраться в этом.

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

Комментарии:

1. Вы читали эту статью? gnu.org/software/gsl/manual/html_node/…

2. Дизайн PRNG не зависит от языка и имеет больше общего с теорией чисел и алгеброй, чем с программированием. Если ваша цель — изучить C на нескольких примерах, вам следует поискать что-то другое. Если вы хотите понять дизайн PRNG, вам следует удалить части, упоминающие C .

3. @Seth Carnegie Я прочитал эту статью, но я действительно не мог понять, что она пыталась сказать.

4. @Cistoran: Понимание того, что делает хороший RNG, требует больших знаний математики; статистики, теории чисел, теории групп и т.д. (большая часть из которых выходит за рамки моих знаний и терпения). Это не то, чем я бы рекомендовал вам заниматься случайно. Есть гораздо более полезные вещи, которым нужно научиться, учитывая, что, как вы говорите, это было бы изобретением колеса.

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

Ответ №1:

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

Примерами действительно генераторов случайных чисел являются те, которые улавливают случайный шум из природы и оцифровывают его. К ним относятся:

http://www.fourmilab.ch/hotbits/

http://www.random.org/

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

http://www.lavarnd.org/

http://www.idquantique.com/true-random-number-generator/products-overview.html

http://www.araneus.fi/products-alea-eng.html

Что касается генераторов псевдослучайных чисел, то самыми простыми в освоении (и которые обычный непрофессионал, вероятно, мог бы создать самостоятельно) являются линейные конгруэнтные генераторы. К сожалению, это также одни из худших PRNG, которые существуют.

Некоторые рекомендации по определению того, что такое хороший PRNG, включают:

  1. Периодичность (каков диапазон доступных чисел?)
  2. Последовательные числа (какова вероятность того, что одно и то же число повторится дважды подряд)
  3. Единообразие (такая же вероятность выбора чисел из определенного поддиапазона, как и из другого поддиапазона)
  4. Сложность в обратном проектировании (если оно близко к действительно случайному, то кто-то не сможет вычислить следующее число, которое оно генерирует, на основе последних нескольких чисел, которые оно сгенерировало)
  5. Скорость (как быстро я могу сгенерировать новое число? Требуется ли для этого 5 или 500 арифметических операций)
  6. Я уверен, что есть другие, которых мне не хватает

Одним из наиболее популярных прямо сейчас, который считается хорошим в большинстве приложений (т. Е. не криптографии) является Mersenne Twister. Как вы можете видеть по ссылке, это простой алгоритм, возможно, всего 30 строк кода. Однако попытка придумать эти 20 или 30 строк кода с нуля требует больших умственных усилий и изучения PRNGS. Обычно самые известные алгоритмы разрабатываются профессором или профессионалом отрасли, который десятилетиями изучал PRNGS.

Я надеюсь, что вы изучаете PRNGS и пытаетесь внедрить свои собственные (попробуйте «Искусство компьютерного программирования Кнута» или «Числовые рецепты» в качестве отправной точки), но я просто хотел изложить все это, так что в конце дня (если PRNGS не будет делом вашей жизни) гораздо лучше просто использовать то, что придумал кто-то другой. Также, в связи с этим, я хотел бы отметить, что исторически компиляторы, электронные таблицы и т.д. Не используют то, что большинство математиков считают хорошими PRNGS, поэтому, если вам нужны высококачественные PRNGS, Не используйте стандартную библиотеку one в C , Excel, .NET, Java и т.д., Пока вы не изучите, с помощью чего они это реализуют.

Комментарии:

1. Повторно «Сложность в обратном проектировании»: это проблема для криптографически защищенных PRNG, но не для PRNG в целом. Типичное использование PRNG — добавить немного случайности в компьютерную игру или в симуляцию Монте-Карло. Здесь нет необходимости в безопасном PRNG для таких приложений. OTOH, если вы используете PRNG для шифрования сообщения или цифровой подписи, то опасения по поводу обратного проектирования выходят на первый план.

Ответ №2:

Обычно используется линейный конгруэнтный генератор, и в вики-статье это довольно хорошо объясняется.

Комментарии:

1. Не совсем. В частности, там говорится: «Наиболее эффективные LCGS имеют m, равное степени 2, чаще всего m = 2 ^ 32 или m = 2 ^ 64». Было доказано, что вы не можете получить хороший генератор, когда m он равен двум; m должен быть простым. Ссылка на линейные конгруэнтные генераторы — «Генераторы случайных чисел: хорошие трудно найти», Парк и Миллер, CACM, октябрь 1988.

2. @James Замечательная особенность Википедии в том, что такие пользователи, как вы, могут редактировать и улучшать ее. Также обратите внимание, что здесь написано «эффективный», а не «хороший». Если вы хотите хороший PRNG, вам вообще не следует использовать LCG.

Ответ №3:

Цитируя Джона фон Неймана:

Любой, кто рассматривает арифметические методы получения случайных цифр, конечно, находится в состоянии греха.

Это взято из главы 3 «Случайные числа» книги Кнута «Искусство компьютерного программирования», которая, должно быть, представляет собой наиболее исчерпывающий обзор предмета, доступный. И как только вы прочтете это, вы будете исчерпаны. Вы также узнаете, почему вы не хотите писать свой собственный генератор случайных чисел.

Ответ №4:

Правильное решение наилучшим образом соответствует требованиям, а требования каждой ситуации будут уникальными. Вероятно, это самый простой способ добиться этого:

  • Создайте большой одномерный массив, заполненный «реальными» случайными значениями.
  • «затравите» ваш псевдослучайный генератор, вычисляя начальный индекс с учетом системного времени.
  • Выполните итерацию по массиву и возвращайте значение для каждого вызова вашей функции.
  • Завершите, когда он дойдет до конца.