Как в 1С определить, чётное число или нечётное

· 9 мин

Содержание

Чётность числа во встроенном языке 1С проверяют одной строкой: Цел(Число / 2) * 2 = Число. Если выражение истинно — число чётное, если ложно — нечётное. Готового оператора %, как в Python или C, и отдельной функции остатка в языке 1С нет, поэтому опытные разработчики определяют чётное число через целую часть от деления.

Разберём рабочую функцию, вариант с вычислением самого остатка, поведение на дробных и отрицательных значениях, обработку массива чисел и типичные промахи. Все примеры рассчитаны на 1С:Предприятие 8.3 — встроенный язык одинаков в любой конфигурации на этой платформе, будь то Бухгалтерия, ЗУП, Управление торговлей или собственная разработка. Поэтому код ниже переносится без изменений.

Базовая функция проверки чётности

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

Функция ЭтоЧётное(Число)
    Возврат Цел(Число / 2) * 2 = Число;
КонецФункции

Логика простая. Цел() возвращает целую часть числа, отбрасывая дробь. Для чётного числа деление на 2 даёт ровно целое значение, и после обратного умножения на 2 мы получаем исходное число. Для нечётного — дробь теряется, и равенство не выполняется.

Проверим вручную:

  • Цел(8 / 2) * 2 = Цел(4) * 2 = 8 → равно 8, число чётное.
  • Цел(7 / 2) * 2 = Цел(3.5) * 2 = 3 * 2 = 6 → не равно 7, число нечётное.

Вызов в коде:

Если ЭтоЧётное(Количество) Тогда
    Сообщить("Количество чётное");
Иначе
    Сообщить("Количество нечётное");
КонецЕсли;

Цел() именно отбрасывает дробную часть, а не округляет. Это и нужно для проверки чётности — округление дало бы неверный результат на значениях вроде 4,5.

Почему во встроенном языке нет оператора %

Разработчики, пришедшие из других языков, первым делом пробуют написать Число % 2 = 0. Во встроенном языке 1С такого оператора нет: арифметика ограничена сложением, вычитанием, умножением и делением. Поэтому остаток от деления здесь вычисляют вручную.

Формула остатка выводится из той же целой части:

Остаток = Число - Цел(Число / Делитель) * Делитель;

Для проверки чётности делитель равен 2:

Остаток = Число - Цел(Число / 2) * 2;
Если Остаток = 0 Тогда
    // число чётное
КонецЕсли;

Вариант с остатком удобен, когда само значение остатка нужно дальше — например, при распределении номеров по группам или при проверке кратности не только двум, но и трём, пяти, десяти. Если же нужен только ответ «да/нет», короче сравнивать напрямую через Цел(Число / 2) * 2 = Число.

Коротко о том, какой приём когда брать:

ПриёмВыражениеКогда применять
Прямое сравнениеЦел(Число / 2) * 2 = Числонужен только ответ «чётное/нечётное»
Через остатокЧисло - Цел(Число / 2) * 2нужно само значение остатка
Отдельная функцияЭтоЧётное(Число)проверка встречается в коде много раз

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

Не ищите в синтаксис-помощнике функцию «Остаток» — её во встроенном языке нет, остаток всегда считается выражением через Цел().

Дробные числа: сначала приводим к целому

Понятие чётности определено только для целых чисел. Вопрос «чётное ли 4,7» смысла не имеет, поэтому дробное значение сначала надо привести к целому — и только потом проверять.

Здесь важно осознанно выбрать, как именно отбросить дробь:

  • Цел(Число) — отбрасывает дробную часть (4,7 → 4; 4,2 → 4).
  • Окр(Число, 0) — округляет по правилам арифметики (4,7 → 5; 4,2 → 4).

Разные способы дают разную чётность для одного исходного значения, поэтому решение зависит от задачи. Если число получено делением или расчётом и по смыслу должно быть целым, обычно его округляют:

ЦелоеЗначение = Окр(Число, 0);
Если Цел(ЦелоеЗначение / 2) * 2 = ЦелоеЗначение Тогда
    Сообщить("После округления число чётное");
КонецЕсли;

Если число пришло из расчёта с делением, возможна погрешность вычислений с плавающей точкой. Перед проверкой чётности приведите значение к нужной разрядности через Окр(), иначе «целое на вид» число может оказаться 7,0000001.

Отрицательные числа и ноль

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

Проверим:

  • Цел(-4 / 2) * 2 = Цел(-2) * 2 = -4 → равно -4, чётное.
  • Цел(-3 / 2) * 2 = Цел(-1.5) * 2 = -1 * 2 = -2 → не равно -3, нечётное.

Ноль по математическому определению чётный, и формула это подтверждает: Цел(0 / 2) * 2 = 0. Отдельной обработки нуля не требуется — та же функция ЭтоЧётное() вернёт для него Истина.

Результат функции — значение типа Булево, поэтому его сразу подставляют в условие или присваивают реквизиту: Если ЭтоЧётное(Номер) Тогда …. Дополнительно сравнивать с Истина не нужно — это лишняя запись.

Проверка чётности в запросе

В языке запросов 1С отдельной функции остатка от деления тоже нет. Поэтому для списков удобнее поступать одним из двух способов.

Первый — получить данные запросом, а признак чётности вычислить в модуле после выборки:

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Если Цел(Выборка.Номер / 2) * 2 = Выборка.Номер Тогда
        // строка с чётным номером
    КонецЕсли;
КонецЦикла;

Второй — если чередование нужно прямо в результате запроса, выразите тот же остаток в вычисляемом поле через целую часть (Цел() доступна и в запросе). Но на практике проверку чётности почти всегда проще и нагляднее делать в коде после выборки — там её легко изменить и отладить.

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

Обработка массива чисел

Когда чисел много, функцию чётности применяют в цикле. Типовая задача — посчитать, сколько в массиве чётных элементов, или разложить их по двум коллекциям.

ЧётныеЧисла = Новый Массив;
НечётныеЧисла = Новый Массив;

Для Каждого Элемент Из ИсходныйМассив Цикл
    Если Цел(Элемент / 2) * 2 = Элемент Тогда
        ЧётныеЧисла.Добавить(Элемент);
    Иначе
        НечётныеЧисла.Добавить(Элемент);
    КонецЕсли;
КонецЦикла;

Сообщить("Чётных: " + ЧётныеЧисла.Количество());

Для таблицы значений схема та же — перебор Для Каждого Строка Из ТаблицаЗначений Цикл и проверка нужной колонки:

Для Каждого Строка Из ТаблицаДокументов Цикл
    Строка.ЧётныйНомер = ЭтоЧётное(Строка.Номер);
КонецЦикла;

Выносите саму проверку в функцию ЭтоЧётное() и вызывайте её внутри цикла: так код читается лучше и правка формулы делается в одном месте. Если по массиву нужно не разложить элементы, а, например, обнулить каждый второй или сложить только чётные — меняется только тело условия, а сама проверка остаётся прежней.

О «побитовой оптимизации» и проверке младшего бита, как в C, на платформе 1С думать не стоит. Арифметика здесь не узкое место — время съедают запросы к базе и чтение объектов, а не сравнение Цел(Число / 2) * 2. Выигрыш от микротрюков незаметен, а читаемость падает.

Типичные ошибки

Ошибки в проверке чётности почти всегда сводятся к нескольким повторяющимся ситуациям.

  • 🔸 Попытка применить оператор %. Код Число % 2 просто не скомпилируется — такого оператора во встроенном языке нет.
  • 🔸 Проверка дробного числа напрямую. Цел(4.7 / 2) * 2 даст 4, что не равно 4,7, и любое дробное число будет «нечётным». Сначала приведите значение к целому.
  • 🔸 Путаница Цел() и Окр(). Для отбрасывания дроби нужен Цел(). Окр() без второго аргумента тоже округляет, и результат проверки может измениться.
  • 🔸 Сравнение с погрешностью. После деления значение бывает не ровно целым из-за вычислений с плавающей точкой. Приводите к разрядности через Окр(Число, 0) до проверки.
  • 🔸 Строка вместо числа. Если значение пришло из реквизита типа «Строка», деление вызовет ошибку. Приведите его к числу функцией Число().
  • 🔸 Хранение признака чётности в базе. Чётность — вычисляемое свойство. Не заводите под него отдельный реквизит: при изменении номера сохранённое значение разойдётся с реальным. Считайте чётность в момент вывода, а не держите в данных.
Проверьте себя
Чему равно `Цел(7 / 2)` в 1С?
Какое выражение истинно для чётного значения переменной Число?
Есть ли во встроенном языке 1С оператор `%` для остатка от деления?

Где это пригодится на практике

Проверка чётности редко бывает самоцелью — обычно она часть более крупной задачи.

Чередование строк в выводе. Чтобы подсветить каждую вторую строку таблицы или отчёта, заводят счётчик строк и по его чётности меняют оформление:

Счётчик = 0;
Для Каждого Строка Из Данные Цикл
    Счётчик = Счётчик + 1;
    ЧётнаяСтрока = ЭтоЧётное(Счётчик);
    // по ЧётнаяСтрока выбираем цвет/стиль строки
КонецЦикла;

Счётчик увеличивают вручную в цикле вывода, а не берут из данных — так чередование остаётся ровным даже при фильтрах и сортировке, когда исходные номера идут не подряд.

Разнесение по двум потокам. Пакетную обработку иногда делят на два набора — например, чётные и нечётные номера документов обрабатывают разными процедурами. Схема — та же, что в примере с массивом выше.

Контроль ввода. Если по регламенту некоторый реквизит должен быть кратен двум (количество в упаковке, парные позиции), проверку чётности ставят в обработчик проверки заполнения и не дают провести документ с нечётным значением.

Разметка периодов и нумерация. Чередование «чёт/нечёт» используют для разметки недель, смен, мест — везде, где две группы должны идти через одну.

Во всех случаях ядро одно — функция ЭтоЧётное() из первого раздела.

Тот же приём работает и для проверки кратности любому другому числу — достаточно заменить двойку на нужный делитель. Например, кратность трём или десяти:

Функция КратноЛи(Число, Делитель)
    Возврат Цел(Число / Делитель) * Делитель = Число;
КонецФункции

Вызов КратноЛи(Сумма, 10) ответит, кратна ли сумма десяти, КратноЛи(Количество, 3) — делится ли количество на три без остатка. Это удобно для контроля комплектов, фасовки по упаковкам и округления партий. Написав одну универсальную функцию, вы закрываете и проверку чётности (делитель 2), и любую другую кратность.

Частые вопросы

Чем заменить оператор `%` из других языков?
Выражением Число - Цел(Число / Делитель) * Делитель — оно возвращает остаток от деления. Для проверки чётности делитель равен 2, а для признака «да/нет» короче сравнивать Цел(Число / 2) * 2 = Число.
Почему для отбрасывания дроби берут `Цел()`, а не `Окр()`?
Цел() отбрасывает дробную часть, а Окр() округляет. В проверке чётности нужно именно отбрасывание: при округлении, например, 4,5 превратилось бы в 5 и результат проверки был бы неверным.
Как вывести из списка только чётные позиции?
Получите данные запросом, а в цикле по выборке проверяйте нужную колонку через Цел(Поле / 2) * 2 = Поле. Отбирать чётность прямо в условии запроса неудобно — проще сделать это в модуле.
Правильно ли формула работает с отрицательными числами?
Да. Цел() отбрасывает дробь в сторону нуля одинаково для плюса и минуса, поэтому -4 определяется как чётное, -3 — как нечётное, а 0 — как чётное.
Есть ли разница по скорости между способами?
На платформе 1С — нет. Любой из вариантов через Цел() выполняется мгновенно; реальное время в обработке занимают запросы и чтение объектов, а не арифметика. Оптимизировать саму проверку чётности смысла нет.