Разработка и Конфигурация · 10 мин
Как заполнить массив случайными числами в 1С
Как заполнить массив случайными числами в 1С: генератор случайных чисел, цикл заполнения, уникальные значения, примеры кода и типичные ошибки.
Во встроенном языке 1С нет привычной функции вида «СлучайноеЧисло(мин, макс)», поэтому заполнение массива случайными числами делается через объект ГенераторСлучайныхЧисел и обычный цикл. Задача встречается при тестировании отчётов, генерации учебных данных, перемешивании выборок и проверке алгоритмов на случайных наборах. Разобравшись с двумя-тремя приёмами, вы сможете получать как простые, так и уникальные случайные наборы.
Ключевой объект — ГенераторСлучайныхЧисел. Он создаётся либо с указанием начального числа (seed), либо без него, и выдаёт псевдослучайные целые числа методом СлучайноеЧисло(НижняяГраница, ВерхняяГраница). Границы включаются в диапазон, то есть вызов СлучайноеЧисло(1, 10) может вернуть и 1, и 10.
Важно понимать природу генератора: числа псевдослучайные, то есть воспроизводимые при одинаковом начальном значении. Для тестов это плюс (можно повторить сценарий), для криптографических задач — минус, так как для защиты данных такой генератор не предназначен.
Создание генератора случайных чисел
Объект создаётся конструктором Новый ГенераторСлучайныхЧисел(). Если передать в конструктор число — это будет начальное значение последовательности. При одинаковом seed генератор выдаст одну и ту же последовательность чисел, что удобно для воспроизводимых тестов.
Если конструктор вызван без параметра, начальное значение формируется системой автоматически, и последовательность при каждом запуске будет отличаться. Именно этот вариант обычно нужен, когда требуется «разная случайность» при каждом выполнении кода.
// Воспроизводимая последовательность (для тестов)
ГСЧ = Новый ГенераторСлучайныхЧисел(12345);
// Разная последовательность при каждом запуске
ГСЧ = Новый ГенераторСлучайныхЧисел();
Типичная ошибка — создавать генератор внутри цикла на каждой итерации. Если инициализация происходит слишком быстро подряд, автоматический seed может не успеть измениться, и вы получите массив из одинаковых чисел. Генератор создаётся один раз до цикла.
Базовое заполнение массива в цикле
Простейший сценарий: массив из N элементов, каждый — случайное число в заданном диапазоне. Используется цикл со счётчиком и метод Добавить().
Функция ЗаполнитьМассивСлучайными(Количество, Мин, Макс)
Массив = Новый Массив;
ГСЧ = Новый ГенераторСлучайныхЧисел();
Для Сч = 1 По Количество Цикл
Массив.Добавить(ГСЧ.СлучайноеЧисло(Мин, Макс));
КонецЦикла;
Возврат Массив;
КонецФункции
Вызов ЗаполнитьМассивСлучайными(10, 1, 100) вернёт массив из десяти чисел от 1 до 100 включительно. Повторы значений допускаются — генератор не отслеживает уже выданные числа.
- 1Объявите массив: Новый Массив
- 2Создайте генератор один раз: Новый ГенераторСлучайныхЧисел()
- 3В цикле от 1 до нужного количества вызывайте СлучайноеЧисло(Мин, Макс)
- 4Добавляйте результат в массив методом Добавить()
- 5Проверьте размер массива через Количество() и выведите значения для контроля
Массив из уникальных случайных чисел
Если повторы недопустимы (например, случайный отбор строк без дублирования), перед добавлением проверяйте наличие значения методом Найти(). Цикл при этом становится циклом с условием, потому что число итераций заранее неизвестно.
Функция УникальныеСлучайныеЧисла(Количество, Мин, Макс)
Массив = Новый Массив;
ГСЧ = Новый ГенераторСлучайныхЧисел();
Пока Массив.Количество() < Количество Цикл
Число = ГСЧ.СлучайноеЧисло(Мин, Макс);
Если Массив.Найти(Число) = Неопределено Тогда
Массив.Добавить(Число);
КонецЕсли;
КонецЦикла;
Возврат Массив;
КонецФункции
У этого подхода есть жёсткое ограничение: количество запрашиваемых чисел не должно превышать ширину диапазона. Если попросить 20 уникальных чисел из диапазона 1–10, цикл никогда не завершится. Всегда проверяйте условие Количество <= Макс - Мин + 1 до начала генерации.
Для больших диапазонов эффективнее хранить уже выбранные значения в соответствии: поиск ключа в соответствии быстрее, чем линейный поиск по массиву методом Найти().
Случайные числа с дробной частью
Метод СлучайноеЧисло возвращает только целые значения. Если нужны дробные числа, стандартный приём — сгенерировать целое в расширенном диапазоне и разделить на степень десяти.
// Случайное число от 0 до 1 с двумя знаками после запятой
Дробное = ГСЧ.СлучайноеЧисло(0, 100) / 100;
// Случайное число от 10,00 до 99,99
Дробное = ГСЧ.СлучайноеЧисло(1000, 9999) / 100;
Точность результата определяется выбранным делителем: деление на 100 даёт два знака, на 1000 — три. Учитывайте, что при дальнейших вычислениях платформа может применять банковское округление в ряде операций, поэтому для финансовых расчётов округляйте результат явно функцией Окр().
Перемешивание существующего массива
Смежная задача — не сгенерировать числа, а случайно перемешать уже имеющийся массив (например, порядок вопросов в тесте). Классический алгоритм — тасование Фишера–Йетса: проходим массив с конца и меняем текущий элемент со случайным из левой части.
Процедура ПеремешатьМассив(Массив)
ГСЧ = Новый ГенераторСлучайныхЧисел();
Для Инд = Массив.ВГраница() По 1 Цикл Шаг -1
// в 1С: Для Инд = 1 По Массив.ВГраница() Цикл с обратным индексом
Прервать; // см. вариант ниже
КонецЦикла;
КонецПроцедуры
Во встроенном языке нет цикла с шагом -1, поэтому обратный проход реализуют через вычисление индекса:
Процедура ПеремешатьМассив(Массив)
ГСЧ = Новый ГенераторСлучайныхЧисел();
Для Сч = 0 По Массив.ВГраница() - 1 Цикл
Инд = Массив.ВГраница() - Сч;
СлучИнд = ГСЧ.СлучайноеЧисло(0, Инд);
Врем = Массив[Инд];
Массив[Инд] = Массив[СлучИнд];
Массив[СлучИнд] = Врем;
КонецЦикла;
КонецПроцедуры
Такое перемешивание равномерно: каждая перестановка равновероятна. Наивный вариант «поменять каждый элемент со случайным по всему массиву» даёт смещённое распределение и для тестовых заданий нежелателен.
Проверка результата и воспроизводимость
После заполнения полезно убедиться, что массив соответствует ожиданиям: размер совпадает с запрошенным, значения не выходят за границы, при требовании уникальности дублей нет. Для быстрого контроля достаточно вывести элементы в сообщение.
Для Каждого Элемент Из Массив Цикл
Сообщить(Элемент);
КонецЦикла;
Если случайные данные используются в тестах, зафиксируйте seed в константе или параметре теста. Тогда при падении теста вы сможете воспроизвести ровно ту же последовательность чисел и локализовать проблему, а не гоняться за «плавающей» ошибкой.
Как проверить результат
Массив.Количество() равно запрошенному числу элементов
Элементов меньше или больше — проверьте границы цикла
Все элементы в пределах от Мин до Макс включительно
Есть значения вне диапазона — перепутаны аргументы СлучайноеЧисло
Найти() для каждого элемента возвращает только один индекс
Дубли при требовании уникальности — отсутствует проверка перед Добавить()
Элементы различаются при каждом запуске
Весь массив из одинаковых чисел — генератор создан внутри цикла
Выбор подхода под задачу
Простой цикл с Добавить() подходит, когда дубли допустимы: заполнение тестовых таблиц, имитация показателей, нагрузочные данные. Это самый быстрый и короткий вариант кода.
Проверка через Найти() или соответствие нужна для уникальных выборок: случайный отбор сотрудников для проверки, формирование неповторяющихся номеров заданий. Для небольших массивов (до нескольких сотен элементов) разница в скорости незаметна, для больших — используйте соответствие.
Тасование Фишера–Йетса применяйте, когда набор значений уже известен и нужно лишь изменить порядок, — это корректнее, чем генерировать случайные индексы и бороться с дублями.
Сравнение вариантов
Подходит для быстрого заполнения с допустимыми повторами; минимум кода
Уникальные значения на небольших объёмах; требует контроля ширины диапазона
Уникальные значения на больших объёмах; быстрый поиск дублей
Перемешивание готового набора без дублей; не генерирует новые значения
Часто задаваемые вопросы
Почему массив заполняется одинаковыми числами?
Чаще всего генератор создаётся внутри цикла, и при быстром выполнении каждый экземпляр получает одно и то же автоматическое начальное значение. Вынесите создание объекта ГенераторСлучайныхЧисел перед циклом — проблема исчезнет.
Включаются ли границы в диапазон СлучайноеЧисло(Мин, Макс)?
Да, обе границы включаются. Вызов СлучайноеЧисло(1, 6) моделирует бросок кубика и может вернуть как 1, так и 6. Если верхняя граница не нужна, уменьшите аргумент на единицу.
Как получить одинаковую последовательность при каждом запуске?
Передайте в конструктор фиксированное число: Новый ГенераторСлучайныхЧисел(42). Пока seed неизменен, последовательность выдаваемых чисел будет полностью повторяться, что удобно для отладки и автотестов.
Можно ли использовать генератор для паролей и ключей?
Нет. ГенераторСлучайныхЧисел выдаёт псевдослучайную воспроизводимую последовательность и не обеспечивает криптографической стойкости. Для паролей, токенов и ключей применяйте специализированные средства защиты, а не встроенный ГСЧ.
Как избежать бесконечного цикла при генерации уникальных чисел?
Перед запуском проверьте, что запрошенное количество не превышает число возможных значений: Количество <= Макс - Мин + 1. Если условие нарушено, возвращайте ошибку или расширяйте диапазон — иначе цикл Пока никогда не завершится.
Работает ли ГенераторСлучайныхЧисел на веб-клиенте?
Да, объект доступен на тонком, толстом и веб-клиенте, а также на сервере. Код заполнения массива не требует адаптации под режим исполнения, но помните про ограничения контекста при передаче массива между клиентом и сервером.