Разработка и Конфигурация · 10 мин
Как найти простые числа в 1С: алгоритмы, код и оптимизация
Как найти простые числа в 1С: проверка делителями, решето Эратосфена, готовые процедуры на встроенном языке, оптимизация и типичные ошибки.
Простые числа — натуральные числа больше единицы, которые делятся только на себя и на единицу. Задача их поиска в 1С возникает в учебных проектах, при генерации контрольных ключей, в задачах криптографии и при подготовке к собеседованиям. Встроенный язык 1С не содержит готовой функции проверки простоты, поэтому алгоритм реализуют вручную — и это хорошая возможность разобраться в оптимизации циклов.
Существует два базовых подхода: проверка каждого числа перебором делителей и решето Эратосфена, которое находит все простые числа диапазона за один проход. Первый подходит для единичных проверок, второй — когда нужен список простых чисел до заданной границы. Ниже разобраны оба метода с готовым кодом, который можно вставить в общий модуль или обработку.
Важный нюанс: встроенный язык 1С работает медленнее компилируемых языков, поэтому для больших диапазонов (миллионы чисел) стоит учитывать производительность и ограничивать область поиска. Для типовых задач — до нескольких сотен тысяч чисел — приведённые решения работают за секунды.
Как проверить, является ли число простым
Наивный способ — перебрать все делители от 2 до N−1 — работает, но избыточен. Достаточно проверить делители до квадратного корня из числа: если у числа есть делитель больше корня, то парный ему делитель обязательно меньше корня и уже был найден. Это сокращает количество итераций с N до примерно √N.
Дополнительная оптимизация — отдельно обработать чётные числа: если число больше 2 и делится на 2, оно сразу составное. После этого перебирать можно только нечётные делители с шагом 2, что вдвое уменьшает число итераций.
Готовая функция для общего модуля:
Функция ЭтоПростоеЧисло(Число) Экспорт
Если Число < 2 Тогда
Возврат Ложь;
КонецЕсли;
Если Число = 2 Тогда
Возврат Истина;
КонецЕсли;
Если Число % 2 = 0 Тогда
Возврат Ложь;
КонецЕсли;
Граница = Цел(Sqrt(Число));
Для Делитель = 3 По Граница Цикл
Если Делитель % 2 = 0 Тогда
Продолжить;
КонецЕсли;
Если Число % Делитель = 0 Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Обратите внимание на крайние случаи: единица и ноль не являются простыми, двойка — единственное чётное простое число. Отрицательные числа функция также отклоняет условием Число < 2.
Решето Эратосфена для поиска всех простых чисел диапазона
Когда нужно найти не одно число, а все простые до заданной границы, перебор с проверкой каждого числа становится расточительным. Решето Эратосфена решает задачу элегантнее: создаётся массив флагов, и последовательно вычёркиваются все числа, кратные уже найденным простым.
Алгоритм: заполняем массив значениями «Истина», затем для каждого простого числа p начиная с 2 помечаем как составные все его кратные, начиная с p². Начинать именно с квадрата важно — все меньшие кратные уже вычеркнуты при обработке предыдущих простых чисел.
Функция НайтиПростыеЧисла(ВерхняяГраница) Экспорт
Результат = Новый Массив;
Если ВерхняяГраница < 2 Тогда
Возврат Результат;
КонецЕсли;
// Индекс массива соответствует числу (0 и 1 не используются)
Флаги = Новый Массив(ВерхняяГраница + 1);
Для Инд = 0 По ВерхняяГраница Цикл
Флаги[Инд] = Истина;
КонецЦикла;
Флаги[0] = Ложь;
Флаги[1] = Ложь;
ГраницаКорня = Цел(Sqrt(ВерхняяГраница));
Для Текущее = 2 По ГраницаКорня Цикл
Если Флаги[Текущее] Тогда
Кратное = Текущее * Текущее;
Пока Кратное <= ВерхняяГраница Цикл
Флаги[Кратное] = Ложь;
Кратное = Кратное + Текущее;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Для Инд = 2 По ВерхняяГраница Цикл
Если Флаги[Инд] Тогда
Результат.Добавить(Инд);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Как вывести результат в обработке или отчёте
Полученный массив удобно вывести через таблицу значений на форме обработки. Создайте реквизит формы типа «ТаблицаЗначений» с колонкой «ПростоеЧисло», добавьте её на форму, а в команде заполнения загрузите массив из функции решета.
Пример команды формы:
&НаКлиенте
Процедура НайтиПростые(Команда)
НайтиПростыеНаСервере(ВерхняяГраница);
КонецПроцедуры
&НаСервере
Процедура НайтиПростыеНаСервере(Граница)
ТаблицаПростых.Очистить();
МассивПростых = НайтиПростыеЧисла(Граница);
Для Каждого Число Из МассивПростых Цикл
НоваяСтрока = ТаблицаПростых.Добавить();
НоваяСтрока.ПростоеЧисло = Число;
КонецЦикла;
КонецПроцедуры
Тяжёлое вычисление выполняется на сервере, клиентская процедура только инициирует вызов. Если расчёт занимает больше пары секунд, выведите индикатор длительной операции или предупреждение, чтобы пользователь не считал программу зависшей.
- 1Создайте внешнюю обработку или общий модуль для функций поиска
- 2Добавьте функцию ЭтоПростоеЧисло для единичных проверок
- 3Добавьте функцию НайтиПростыеЧисла с решетом Эратосфена для диапазонов
- 4Создайте форму с полем верхней границы и таблицей результата
- 5Проверьте работу на известных данных: до 20 должно быть 8 простых чисел
Сравнение методов: когда что выбирать
Выбор алгоритма зависит от постановки задачи. Проверка одного числа делителями эффективна при единичных вызовах и не требует памяти под массив. Решето выигрывает, когда нужно много простых чисел сразу: оно находит их все за один проход вместо повторных проверок.
| Критерий | Проверка делителями | Решето Эратосфена |
|---|---|---|
| Задача | Проверить одно число | Найти все простые до N |
| Память | Почти не требует | Массив размером N+1 |
| Скорость на диапазоне | Медленнее при больших N | Значительно быстрее |
| Сложность реализации | Минимальная | Средняя |
Сравнение вариантов
Подходит для проверки отдельных чисел и малых диапазонов; не требует дополнительной памяти, но медленен на больших списках
Оптимально для получения всех простых чисел до границы; требует массива флагов, поэтому ограничено доступной памятью
Для фиксированных небольших диапазонов можно хранить список в макете или константе и не считать вовсе
Производительность и ограничения платформы
Встроенный язык 1С интерпретируемый, поэтому циклы в нём заметно медленнее, чем в компилируемых языках. Решето до ста тысяч выполняется практически мгновенно, до миллиона — в пределах нескольких секунд, а дальше время растёт ощутимо. Для очень больших диапазонов имеет смысл выносить расчёт во внешнюю компоненту или выполнять его вне 1С.
Следите за типом данных: при больших границах произведение Текущее * Текущее должно оставаться в допустимом диапазоне числового типа. Для практических задач в рамках типовых прикладных решений переполнение маловероятно, но при экспериментах с границами в миллиарды проверку стоит добавить.
Если поиск простых чисел — часть регламентного задания, запускайте его в фоне и сохраняйте результат в регистр сведений, чтобы не пересчитывать при каждом обращении.
Типичные ошибки при реализации
Отдельная группа ошибок связана с архитектурой: размещение вычислений в клиентской процедуре без директивы &НаСервере, отсутствие проверки введённой пользователем границы на разумные пределы, повторный пересчёт при каждом открытии формы вместо кэширования результата.
Проверка корректности результата
Проверить алгоритм просто: количество простых чисел на известных отрезках давно вычислено. До 10 их 4 (2, 3, 5, 7), до 20 — 8, до 100 — 25, до 1000 — 168. Если ваша функция возвращает эти значения, базовая логика верна.
Как проверить результат
Список: 2, 3, 5, 7 — всего 4 числа
В списке есть 1 или 4, либо пропущена двойка
Ровно 25 чисел, последнее — 97
Количество отличается, есть чётные числа кроме 2
Сама верхняя граница включается, если она простая
Число, равное границе, теряется из-за ошибки в условии цикла
Дополнительный тест — кросс-проверка двух методов: прогоните диапазон через решето и через поэлементную проверку функцией ЭтоПростоеЧисло. Результаты должны совпасть полностью; расхождение укажет на ошибку в одном из алгоритмов.
Что важно запомнить
Для единичной проверки достаточно перебора нечётных делителей до квадратного корня. Для списка простых чисел используйте решето Эратосфена с массивом флагов. Проверяйте результат по известным контрольным значениям и не запускайте тяжёлые вычисления в интерактивном сеансе рабочей базы.
Частые вопросы
Почему единица не считается простым числом?
По определению простое число имеет ровно два различных натуральных делителя. У единицы делитель только один — она сама, поэтому она не относится ни к простым, ни к составным числам. В коде это отсекается условием Число < 2.
Можно ли найти простые числа запросом 1С без кода?
Теоретически можно построить запрос с соединением таблицы чисел самой с собой и проверкой делимости, но такой запрос будет медленным и трудночитаемым. Язык запросов не предназначен для итеративных вычислений — используйте встроенный язык.
Как ускорить решето Эратосфена в 1С?
Храните флаги только для нечётных чисел, уменьшив массив вдвое; начинайте вычеркивание с квадрата простого; не выводите промежуточные сообщения внутри цикла — каждый вызов Сообщить() заметно тормозит выполнение.
Есть ли в 1С встроенная функция проверки простоты числа?
Нет, встроенный язык платформы не содержит такой функции. Доступны только базовые математические операции, включая Sqrt для извлечения корня, поэтому алгоритм реализуется вручную — как показано в примерах выше.
Какой максимальный диапазон разумен для поиска в 1С?
Комфортная граница зависит от сервера, но на практике решето до нескольких миллионов выполняется за приемлемое время. Для больших диапазонов лучше разбивать расчёт на блоки, выполнять его в фоновом задании или выносить во внешний инструмент.
Где разместить функции поиска простых чисел в конфигурации?
Если функции нужны в нескольких местах — в общем модуле с признаком «Сервер». Для разовой задачи достаточно модуля объекта внешней обработки. Экспортируйте функции ключевым словом Экспорт, чтобы вызывать их из других модулей.