Генерация случайных чисел в 1С:Предприятие — задача, с которой сталкиваются разработчики при создании тестовых данных, симуляции бизнес-процессов или реализации игровых механик внутри корпоративных систем. В отличие от классических языков программирования, где для этого есть стандартные библиотеки (например, Math.random() в JavaScript или модуль random в Python), в подходы зависят от версии платформы, требований к качеству случайности и контекста использования.

В этой статье мы разберём 5 рабочих методов генерации случайных чисел — от встроенных функций до реализации алгоритма Мерсенна-Твистера на встроенном языке. Вы узнаете, как избежать типичных ошибок (например, предсказуемости последовательностей), какие нюансы учитывать при работе с 1С:Предприятие 8.2 и 8.3, и когда стоит использовать внешние компоненты для криптографически безопасных решений. Особое внимание уделим генерации уникальных случайных значений без повторений — актуальной задаче для создания тестовых справочников или лотерейных механизмов.

1. Встроенные функции 1С для генерации случайных чисел

Начнём с самого простого: платформа 1С:Предприятие предоставляет две базовые функции для работы со случайностью — СлучайноеЧисло() и СлучайнаяСтрока(). Они доступны во всех конфигурациях без дополнительных настроек, но имеют ограничения, о которых важно знать.

Функция СлучайноеЧисло(Максимум) возвращает псевдослучайное целое число в диапазоне от 0 до Максимум-1. Например, СлучайноеЧисло(100) может вернуть значение от 0 до 99. Главный недостаток — предсказуемость последовательности при повторных запусках программы, так как алгоритм инициализируется фиксированным seed-значением (зависит от времени запуска системы).

  • ✅ Простота использования: Результат = СлучайноеЧисло(1000);
  • ⚠️ Предсказуемость: последовательность повторится при перезапуске 1С.
  • 🔄 Диапазон: только целые числа, верхняя граница не включается.
  • 📊 Применение: тестовые данные, простые симуляции.

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

Сообщить(СлучайнаяСтрока(8)); // Пример вывода: "xK9pLmQ2"
⚠️ Внимание: В 1С:Предприятие 8.2 функция СлучайнаяСтрока() может выдавать повторяющиеся символы чаще, чем в 8.3. Для критических задач проверяйте уникальность результатов.

2. Алгоритм на основе времени: повышаем непредсказуемость

Чтобы избежать повторения последовательностей при перезапуске 1С, можно использовать текущее время в качестве seed-значения. Для этого подойдёт функция ТекущаяДата() или ТекстВВремя() в комбинации с математическими операциями.

Пример кода для генерации числа от 1 до 100 с учётом миллисекунд:

ТекущееВремя = ТекущаяДата();

Миллисекунды = Число(Формат(ТекущееВремя, "SS.ffff")) * 1000;

СлучайныйSeed = Миллисекунды + ДеньНедели(ТекущееВремя);

Результат = (СлучайныйSeed % 100) + 1;

  • ⏱️ Зависимость от времени: каждый запуск даёт разные результаты.
  • 🔢 Диапазон: требуется ручная корректировка (например, % 100 для ограничения до 100).
  • ⚠️ Ограничение: при быстром последовательном вызове (например, в цикле) значения могут повторяться.

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

Seed = ТекстВЧисло(Прав(Формат(ТекущаяДата(), "ДФ=yyyyMMddhhmmss.ffff"), 10)) +

ТекстВЧисло(Прав(УникальныйИдентификатор(), 8));

Ранд = Новый СлучайныеЧисла(Seed);

📊 Какой метод генерации случайных чисел вы используете чаще?
Встроенные функции (СлучайноеЧисло)
Собственный алгоритм на основе времени
Внешние компоненты (CryptoAPI)
Алгоритм Мерсенна-Твистера
Другой вариант

3. Класс "СлучайныеЧисла": объектный подход

Начиная с версии 1С:Предприятие 8.3.6, в платформе появился специализированный класс СлучайныеЧисла, который позволяет гибко настраивать генерацию. Этот класс поддерживает:

  • 🎲 Инициализацию пользовательским seed-значением.
  • 📏 Генерацию чисел в произвольном диапазоне (включая вещественные).
  • 🔄 Перемешивание массивов.

Пример использования:

Генератор = Новый СлучайныеЧисла(ТекстВЧисло(Формат(ТекущаяДата(), "ДФ=yyyyMMddhhmmss")));

// Получаем число от 10 до 20 (включительно)

СлучайноеЗначение = Генератор.Получить(10, 20);

// Перемешиваем массив

МассивЧисел = Новый Массив;

МассивЧисел.Добавить(1);

МассивЧисел.Добавить(2);

МассивЧисел.Добавить(3);

Генератор.Перемешать(МассивЧисел);

Преимущества класса СлучайныеЧисла:

Характеристика Описание
Контроль seed Можно фиксировать начальное значение для воспроизводимости (например, для тестов).
Типы чисел Поддерживает целые (Получить()) и вещественные (ПолучитьВещественное()) числа.
Производительность Быстрее, чем ручная реализация алгоритмов на встроенном языке.
Дополнительные функции Перемешивание массивов, выбор случайного элемента из коллекции.
⚠️ Внимание: В версиях 1С:Предприятие 8.3.5 и ниже класс СлучайныеЧисла отсутствует. Для них используйте альтернативные методы из этой статьи.

4. Реализация алгоритма Мерсенна-Твистера на встроенном языке

Если вам нужны высококачественные псевдослучайные числа с большим периодом повторения (например, для статистического моделирования), можно реализовать алгоритм Мерсенна-Твистера (MT19937) непосредственно в 1С. Этот алгоритм используется в многих стандартных библиотеках (например, в Python или C++) и обеспечивает период повторения 2^19937 - 1.

Ниже приведён упрощённый вариант реализации (полная версия занимает ~200 строк кода):

// Инициализация генератора

Процедура ИнициализироватьМТ(Seed)

MT = Новый Массив(624);

MT[0] = Seed;

Для i = 1 По 623 Цикл

MT[i] = 1812433253 * (MT[i-1] Xor (MT[i-1] >> 30)) + i;

КонецЦикла;

КонецПроцедуры

// Получение следующего случайного числа

Функция СлучайноеМТ()

Если индексMT >= 624 Тогда

// Перемешивание массива (упрощённо)

Для i = 0 По 623 Цикл

y = (MT[i] And 0x80000000) + (MT[(i+1) % 624] And 0x7FFFFFFF);

MT[i] = MT[(i+397) % 624] Xor (y >> 1);

Если (y % 2) = 1 Тогда

MT[i] = MT[i] Xor 2567483615;

КонецЕсли;

КонецЦикла;

индексMT = 0;

КонецЕсли;

y = MT[индексMT];

y = y Xor (y >> 11);

y = y Xor ((y << 7) And 2636928640);

y = y Xor ((y << 15) And 4022730752);

y = y Xor (y >> 18);

индексMT = индексMT + 1;

Возврат y;

КонецФункции

Особенности реализации:

  • 🧮 Точность: требует аккуратной работы с побитовыми операциями (Xor, сдвиги).
  • ⚡ Производительность: медленнее встроенных функций, но качественнее.
  • 🔧 Настройка: можно сохранять/восстанавливать состояние генератора.
Полный код алгоритма Мерсенна-Твистера

Для полноценной реализации потребуется добавить обработку 32-битных чисел, корректные константы и методы для генерации чисел в заданном диапазоне. Полный код занимает ~200 строк и включает процедуры инициализации, перемешивания и выдачи чисел. Пример можно найти в открытых репозиториях 1С (например, на GitHub в проектах с математическими библиотеками).

5. Внешние компоненты для криптографически безопасных чисел

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

  • 🔐 CryptoAPI (через COM-объект CAPICOM или System.Security.Cryptography в .NET).
  • 📦 Специализированные внешние компоненты (например, 1C:Enterprise Cryptography Extension).
  • 🌐 Вызов внешних сервисов (например, random.org через HTTP-запросы).

Пример использования CAPICOM для генерации криптографически безопасного числа:

Попытка

Crypto = Новый COMОбъект("CAPICOM.Utilities.1");

СлучайныеБайты = Crypto.GetRandom(4, 0); // 4 байта = 32-битное число

Результат = ТекстВЧисло(СтрокаИзБайтов(СлучайныеБайты));

Исключение

Сообщить("Ошибка CryptoAPI: " + ОписаниеОшибки());

КонецПопытки;

⚠️ Внимание: Использование CAPICOM требует установленного компонента на клиентских машинах и может не работать в веб-клиенте или на сервере без дополнительных настроек.

Альтернатива — использование .NET-объектов (доступно в управляемых формах):

RNGCrypto = Новый NETОбъект("System.Security.Cryptography.RandomNumberGenerator");

Байты = Новый Массив(4); // 4 байта для 32-битного числа

RNGCrypto.GetBytes(Байты);

Результат = Байты[0] + (Байты[1] 256) + (Байты[2] 65536) + (Байты[3] * 16777216);

6. Генерация уникальных случайных чисел без повторений

Частая задача — сгенерировать набор уникальных случайных чисел (например, для розыгрыша призов или создания тестовых документов с уникальными номерами). Здесь важно избежать коллизий и обеспечить равномерное распределение.

Алгоритм решения:

  1. Создать массив всех возможных значений.
  2. Перемешать его с помощью СлучайныеЧисла.Перемешать().
  3. Извлекать элементы последовательно.

Пример кода для генерации 10 уникальных чисел от 1 до 100:

Генератор = Новый СлучайныеЧисла();

ИсходныйМассив = Новый Массив;

Для i = 1 По 100 Цикл

ИсходныйМассив.Добавить(i);

КонецЦикла;

Генератор.Перемешать(ИсходныйМассив);

УникальныеЧисла = Новый Массив;

Для i = 1 По 10 Цикл

УникальныеЧисла.Добавить(ИсходныйМассив[i-1]);

КонецЦикла;

Для больших диапазонов (например, 1 из 1 000 000) этот метод неэффективен. В таких случаях используйте:

  • 🔢 Алгоритм Фишера-Йетса для перемешивания "на лету".
  • 📊 Хеш-таблицы для отслеживания использованных значений.
  • 🔄 Рекурсивный перебор с проверкой уникальности (медленно, но просто).

☑️ Проверка уникальности случайных чисел

Выполнено: 0 / 4

7. Типичные ошибки и как их избежать

При работе со случайными числами в 1С разработчики часто сталкиваются с следующими проблемами:

  1. Предсказуемость последовательностей: если не инициализировать генератор уникальным seed-значением, числа будут повторяться при перезапуске 1С.
    ⚠️ Внимание: В 1С:Предприятие 8.2 функция СлучайноеЧисло() сбрасывает последовательность при каждом вызове Новый Сеанс. Используйте глобальные переменные для хранения состояния генератора.
  2. Неравномерное распределение: при использовании операции % (остаток от деления) для ограничения диапазона могут возникать искажения. Например, СлучайноеЧисло(100) % 50 даст числа от 0 до 49, но с разной вероятностью.
  3. Переполнение типов: при работе с большими числами (например, СлучайноеЧисло(2^31)) возможны ошибки из-за ограничений типа Число в 1С.
  4. Блокировки в многопользовательском режиме: если генератор используется в транзакциях или на сервере, требуется синхронизация, чтобы избежать коллизий.

Рекомендации по избежанию ошибок:

Проблема Решение
Повторяющиеся последовательности Используйте ТекущаяДата() или УникальныйИдентификатор() для инициализации seed.
Неравномерное распределение Для диапазона [A, B] используйте формулу: A + СлучайноеЧисло(B - A + 1).
Переполнение чисел Разбивайте большие диапазоны на поддиапазоны или используйте строковые представления.
Многопользовательские конфликты Выносите генерацию на клиент или используйте блокировки (НачатьТранзакцию()).
💡

Для тестирования равномерности распределения сгенерируйте 10 000 чисел в диапазоне 1–10 и постройте гистограмму в Excel. Если частоты значений отличаются более чем на 10%, проверьте алгоритм генерации.

8. Практическое применение: примеры использования

Рассмотрим реальные сценарии, где генерация случайных чисел полезна в 1С:

  • 📊 Тестовые данные: заполнение справочников случайными значениями для отладки отчётов.
    Для i = 1 По 100 Цикл
    

    НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();

    НовыйЭлемент.Наименование = "Товар_" + СлучайнаяСтрока(5);

    НовыйЭлемент.Цена = СлучайноеЧисло(10000) / 100;

    НовыйЭлемент.Записать();

    КонецЦикла;

  • 🎲 Лотереи и розыгрыши: случайный выбор победителей из списка участников.
    Участники = Новый Массив;
    

    Участники.Добавить("Иванов");

    Участники.Добавить("Петров");

    Участники.Добавить("Сидорова");

    Генератор = Новый СлучайныеЧисла();

    Победитель = Участники[Генератор.Получить(0, Участники.ВГраница())];

  • 🔒 Генерация паролей: создание временных доступов для пользователей.
    Функция СгенерироватьПароль(Длина = 8)
    

    Символы = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    Результат = "";

    Генератор = Новый СлучайныеЧисла();

    Для i = 1 По Длина Цикл

    Результат = Результат + Сред(Символы, Генератор.Получить(1, СтрДлина(Символы)), 1);

    КонецЦикла;

    Возврат Результат;

    КонецФункции

  • 📈 Моделирование бизнес-процессов: имитация случайных событий (например, отказов оборудования).
💡

Для критических задач (финансовые расчёты, шифрование) всегда используйте внешние криптографические генераторы. Встроенные функции 1С не обеспечивают достаточную энтропию для безопасности.

FAQ: Частые вопросы по генерации случайных чисел в 1С

Можно ли в 1С сгенерировать действительно случайное число, а не псевдослучайное?

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

Почему при использовании СлучайноеЧисло() в цикле значения повторяются?

Это происходит из-за того, что функция инициализируется фиксированным seed-значением при старте сеанса. Решение: используйте класс СлучайныеЧисла с динамическим seed (например, на основе времени) или добавляйте задержку между вызовами.

Как сгенерировать случайную дату в заданном диапазоне?

Преобразуйте диапазон дат в количество секунд и используйте генератор чисел:

Начало = '20200101';

Конец = '20231231';

СлучайныеСекунды = СлучайноеЧисло(Конец - Начало + 1);

СлучайнаяДата = Начало + СлучайныеСекунды;

Учтите, что Конец - Начало возвращает количество дней, а не секунд. Для точности используйте ДобавитьСекунду().

Можно ли использовать генератор случайных чисел в фоновых заданиях?

Да, но учитывайте, что в фоновых заданиях 1С:Предприятие 8.3 может сбрасывать состояние глобальных переменных. Сохраняйте seed-значение генератора в базе данных или передавайте его через параметры задания.

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

Для тестирования используйте статистические тесты:

  1. Сгенерируйте большую выборку (например, 10 000 чисел).
  2. Постройте гистограмму распределения.
  3. Проверьте равномерность с помощью критерия хи-квадрат.
  4. Используйте тесты на случайность (например, тест покером или серий).

Для автоматизации можно интегрировать 1С с Python через COM-соединение и использовать библиотеку scipy.stats.