К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как заполнить массив случайными числами в 1С

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

Во встроенном языке 1С нет привычной функции вида «СлучайноеЧисло(мин, макс)», поэтому заполнение массива случайными числами делается через объект ГенераторСлучайныхЧисел и обычный цикл. Задача встречается при тестировании отчётов, генерации учебных данных, перемешивании выборок и проверке алгоритмов на случайных наборах. Разобравшись с двумя-тремя приёмами, вы сможете получать как простые, так и уникальные случайные наборы.

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

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

Создание генератора случайных чисел

Объект создаётся конструктором Новый ГенераторСлучайныхЧисел(). Если передать в конструктор число — это будет начальное значение последовательности. При одинаковом seed генератор выдаст одну и ту же последовательность чисел, что удобно для воспроизводимых тестов.

Если конструктор вызван без параметра, начальное значение формируется системой автоматически, и последовательность при каждом запуске будет отличаться. Именно этот вариант обычно нужен, когда требуется «разная случайность» при каждом выполнении кода.

// Воспроизводимая последовательность (для тестов)

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

// Разная последовательность при каждом запуске

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

Типичная ошибка — создавать генератор внутри цикла на каждой итерации. Если инициализация происходит слишком быстро подряд, автоматический seed может не успеть измениться, и вы получите массив из одинаковых чисел. Генератор создаётся один раз до цикла.

Базовое заполнение массива в цикле

Простейший сценарий: массив из N элементов, каждый — случайное число в заданном диапазоне. Используется цикл со счётчиком и метод Добавить().

Функция ЗаполнитьМассивСлучайными(Количество, Мин, Макс)

Массив = Новый Массив;

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

Для Сч = 1 По Количество Цикл

Массив.Добавить(ГСЧ.СлучайноеЧисло(Мин, Макс));

КонецЦикла;

Возврат Массив;

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

Вызов ЗаполнитьМассивСлучайными(10, 1, 100) вернёт массив из десяти чисел от 1 до 100 включительно. Повторы значений допускаются — генератор не отслеживает уже выданные числа.

Порядок действий
  1. 1
    Объявите массив: Новый Массив
  2. 2
    Создайте генератор один раз: Новый ГенераторСлучайныхЧисел()
  3. 3
    В цикле от 1 до нужного количества вызывайте СлучайноеЧисло(Мин, Макс)
  4. 4
    Добавляйте результат в массив методом Добавить()
  5. 5
    Проверьте размер массива через Количество() и выведите значения для контроля

Массив из уникальных случайных чисел

Если повторы недопустимы (например, случайный отбор строк без дублирования), перед добавлением проверяйте наличие значения методом Найти(). Цикл при этом становится циклом с условием, потому что число итераций заранее неизвестно.

Функция УникальныеСлучайныеЧисла(Количество, Мин, Макс)

Массив = Новый Массив;

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

Пока Массив.Количество() < Количество Цикл

Число = ГСЧ.СлучайноеЧисло(Мин, Макс);

Если Массив.Найти(Число) = Неопределено Тогда

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

КонецЕсли;

КонецЦикла;

Возврат Массив;

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

У этого подхода есть жёсткое ограничение: количество запрашиваемых чисел не должно превышать ширину диапазона. Если попросить 20 уникальных чисел из диапазона 1–10, цикл никогда не завершится. Всегда проверяйте условие Количество <= Макс - Мин + 1 до начала генерации.

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

Типичные ошибки
01
Запрос уникальных чисел шире диапазона: бесконечный цикл и зависание сеанса
02
Проверка дублей методом Найти() на больших массивах: квадратичный рост времени, лучше соответствие
03
Ожидание, что СлучайноеЧисло(1, 10) не вернёт 10: верхняя граница включается в диапазон
04
Создание генератора внутри цикла: одинаковые числа во всех элементах

Случайные числа с дробной частью

Метод СлучайноеЧисло возвращает только целые значения. Если нужны дробные числа, стандартный приём — сгенерировать целое в расширенном диапазоне и разделить на степень десяти.

// Случайное число от 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. Если условие нарушено, возвращайте ошибку или расширяйте диапазон — иначе цикл Пока никогда не завершится.

Работает ли ГенераторСлучайныхЧисел на веб-клиенте?

Да, объект доступен на тонком, толстом и веб-клиенте, а также на сервере. Код заполнения массива не требует адаптации под режим исполнения, но помните про ограничения контекста при передаче массива между клиентом и сервером.