Линейный конгруэнтный генератор: формула и период

Линейный конгруэнтный генератор (ЛКГ) - это простейший алгоритм получения псевдослучайных чисел, который задаётся всего одной рекуррентной формулой и при этом лежит в основе генераторов стандартных библиотек языков C, Java и Pascal. Разобраться, как он работает, нужно каждому, кто изучает теорию вероятностей, дискретную математику или пишет собственные алгоритмы тестирования. Покрути параметры в калькуляторе ниже - он сразу покажет последовательность и диаграмму рассеяния, а потом мы разберём каждую формулу строго.
Формула линейного конгруэнтного генератора
В основе ЛКГ лежит одна рекуррентная формула:
где - множитель (мультипликативная константа), - приращение (инкремент), - модуль, - начальное значение, называемое зерном или «seed». Каждый следующий элемент порождается из предыдущего умножением на , прибавлением и взятием остатка от деления на . Все числа последовательности лежат в диапазоне от до .
Если , генератор называют мультипликативным конгруэнтным генератором (МКГ); если - смешанным или полным ЛКГ. Мультипликативный вариант не может породить (иначе вся последовательность заглохнет), а смешанный допускает любое начальное зерно.
Период генератора и теорема Халла-Добелла
Главная характеристика ЛКГ - длина периода : через шагов последовательность начнёт повторяться. Максимально возможный период равен . Наивный выбор и легко даёт маленький период - например, при последовательность имеет период всего (зациклится на через несколько шагов).
Теорема Халла-Добелла (Hull-Dobell, 1962) полностью описывает, когда смешанный ЛКГ достигает периода :
Другими словами: должно быть взаимно простым с ; множитель должен делиться на все простые делители ; а если делится на , то и обязан делиться на . Если хотя бы одно из условий нарушено, период окажется строго меньше .

На диаграмме рассеяния пары всегда ложатся на конечное число параллельных прямых - это не дефект реализации, а фундаментальное свойство линейных конгруэнтных генераторов, доказанное в теореме Марсальи (1968). Число прямых равно в двумерном случае и убывает в высших размерностях.
Спектральный тест и качество генератора
Диаграмма рассеяния - простейший визуальный тест качества. Более строгий инструмент - спектральный тест: он измеряет расстояние между соседними параллельными гиперплоскостями в -мерном пространстве, на которые укладываются наборы . Чем больше это расстояние, тем хуже генератор: он порождает числа, которые имеют заметную решёточную структуру, а не распределены равномерно.
Для классического генератора стандарта ANSI C (, , ) спектральный тест выявляет плохую трёхмерную структуру - тройки чисел ложатся всего на 15 плоскостей. Именно поэтому современные стандарты вроде PCG или xorshift заменили ЛКГ более сложными конструкциями, хотя и надстроенными поверх той же базовой идеи.
Стандартные параметры в языках программирования
ЛКГ был основным PRNG в системных библиотеках на протяжении десятилетий:
| Система | |||
|---|---|---|---|
ANSI C (rand) | 1 103 515 245 | 12 345 | |
Java (java.util.Random) | 25 214 903 917 | 11 | |
| Borland C++ | 22 695 477 | 1 | |
| MMIX (Кнут) | 6 364 136 223 846 793 005 | 1 442 695 040 888 963 407 |
Обратите внимание: почти везде - степень двойки. Это удобно для реализации на двоичных ЭВМ: операция mod 2^k выполняется через побитовое И (& (m-1)), то есть без деления. Младшие биты выходной последовательности при степени двойки в модуле имеют значительно меньший период: бит имеет период . Из-за этого в коде rand() % 2 (чётность) ANSI C даёт чередование 0,1,0,1,... - это не случайность, это закономерное следствие структуры генератора.
Пример вычисления вручную
Рассмотрим учебный пример: , , , .
Продолжая, получаем последовательность: , а затем снова . Период равен . Проверим условия Халла-Добелла: (выполнено); , единственный простой делитель - , делится на (выполнено) и на (выполнено). Все три условия в силе - отсюда и полный период.
Частые ошибки
- Подстановка без проверки периода. Мультипликативный ЛКГ () не имеет периода ни при каких и : нулевое зерно даёт постоянную нулевую последовательность, а ненулевые зёрна дают период не более . Для степеней двойки мультипликативный генератор работает только если зерно нечётно.
- Перемешивание знаков при операции mod. В C и C++ оператор
%для отрицательных чисел даёт отрицательный остаток. Если промежуточное значение переполняетint, результат непредсказуем. Используйunsigned longили явный((a * x + c) % m + m) % m. - Использование младших битов. При младший бит меняется с периодом , следующие с периодом и т.д. Для отбора случайного числа из всегда берите старшие биты:
(lcg() >> 16) % N, а неlcg() % N. - Зависимость последовательности от зерна. Зерно полностью определяет всю последовательность. Если программа использует одно и то же начальное значение (например, жёстко прошито), «случайные» числа одинаковы в каждом запуске.
- Ожидание криптостойкости. ЛКГ - не криптографический PRNG. Зная последовательных выходов, можно восстановить , и с помощью алгоритма, работающего за полиномиальное время. Для нужд криптографии применяют CSPRNG.
FAQ
Как выбрать параметры ЛКГ для максимального периода? Используй теорему Халла-Добелла: ; делится на все простые множители ; если , то . При хороший выбор: , (параметры Numerical Recipes). Проверить период легко в калькуляторе выше - выбери пресет или введи собственные значения.
Чем ЛКГ отличается от вихря Мерсенна? Вихрь Мерсенна (Mersenne Twister) имеет период против у типичного ЛКГ. MT проходит спектральный тест в 623 измерениях, тогда как ЛКГ рассыпается уже в 3-10 измерениях. При этом ЛКГ занимает в памяти всего одно число состояния и исполняется за 2-3 операции, а MT требует 625 слов состояния.
Почему диаграмма рассеяния ЛКГ показывает прямые линии? Это прямое следствие линейности формулы: . Каждое значение линейно зависит от , поэтому пара лежит на прямой в кольце . При конечном прямая «заворачивается» и распадается на несколько параллельных отрезков. Число таких линий - мера качества генератора в спектральном тесте.
Коротко
Линейный конгруэнтный генератор порождает последовательность псевдослучайных чисел по формуле . Максимальный период достигается тогда и только тогда, когда выполнены условия теоремы Халла-Добелла: взаимно просто с , а делится на все простые делители (и дополнительно на 4, если ). Главный недостаток ЛКГ - гиперплоскостная структура, видимая на диаграмме рассеяния и разрушающая многомерную равномерность. Тем не менее ЛКГ остаётся стандартом во многих учебных и системных реализациях из-за предельной простоты и высокой скорости.
Читайте также

Абстрактный класс и интерфейс: в чём отличие
Абстрактный класс и интерфейс: чем отличаются в ООП, когда наследовать поведение, а когда задавать контракт, как выбрать на примерах Java, C# и Python.

Алгоритм AdaBoost: как слабые классификаторы дают сильный
Алгоритм AdaBoost простыми словами: адаптивный бустинг, перевзвешивание объектов, формула веса классификатора, итоговый ансамбль и разбор шага на примере с формулами.

Алгоритм CatBoost: бустинг с обработкой категорий
Алгоритм CatBoost простыми словами: упорядоченный бустинг против сдвига прогноза, кодирование категориальных признаков через ordered target statistics, симметричные деревья и разбор типовых задач.