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

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

Как получить число по модулю в 1С

Как получить модуль числа в 1С: функции, выражения Max/Макс, работа с запросами через ВЫБОР, типичные ошибки и примеры кода для встроенного языка.

Задача получить абсолютное значение числа возникает в 1С регулярно: при расчёте расхождений в инвентаризации, сравнении сумм оплат, вычислении отклонений плановых и фактических показателей. Разработчики, пришедшие из других языков, ищут привычную функцию Abs() — и не находят её в синтакс-помощнике, потому что во встроенном языке 1С прямой функции модуля нет.

Тем не менее задача решается несколькими способами: через функции Макс()/Max(), через условный оператор, а в языке запросов — через конструкцию ВЫБОР. Каждый вариант имеет свою область применения, и выбор зависит от того, где выполняется вычисление — в коде модуля, в запросе или в выражении СКД.

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

Почему в 1С нет функции Abs() и что использовать вместо неё

Встроенный язык 1С исторически содержит ограниченный набор математических функций: Цел()/Int(), Окр()/Round(), Макс()/Max(), Мин()/Min(), Log(), Exp() и некоторые другие. Функция абсолютного значения в этот набор не входит, и это частый источник недоразумений у начинающих разработчиков.

Попытка написать Результат = Abs(-15); приведёт к ошибке компиляции «Процедура или функция с указанным именем не определена». Вместо вызова одной функции модуль выражают через имеющиеся средства языка.

Два основных приёма для кода модулей — функция Макс() и условный оператор. Оба дают корректный результат для любых чисел, включая ноль и отрицательные значения с дробной частью.

Получение модуля через функцию Макс()

Самый компактный способ — воспользоваться функцией Макс() (в английском синтаксисе Max()). Идея проста: максимум из числа и его значения с обратным знаком всегда равен модулю. Если число положительное, больше оно само; если отрицательное — больше его противоположное значение.

Пример кода:

Число = -123.45;

МодульЧисла = Макс(Число, -Число);

// МодульЧисла = 123.45

Тот же приём работает и в английском варианте синтаксиса:

Value = -123.45;

AbsValue = Max(Value, -Value);

Способ удобен, когда модуль нужен прямо внутри выражения, без выделения отдельной переменной: например, Если Макс(Разница, -Разница) > ДопустимоеОтклонение Тогда .... Это позволяет уместить проверку в одну строку.

Получение модуля через условный оператор

Второй вариант — классическая проверка знака через Если. Она чуть длиннее, но нагляднее для тех, кто поддерживает код после вас, и легко расширяется дополнительной логикой.

Функция МодульЧисла(Число) Экспорт

Если Число < 0 Тогда

Возврат -Число;

Иначе

Возврат Число;

КонецЕсли;

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

Такую функцию имеет смысл один раз разместить в общем модуле (например, в модуле работы с числами или утилитах) и вызывать отовсюду. Это избавляет от дублирования логики и упрощает чтение кода: вызов МодульЧисла(Отклонение) понятнее, чем Макс(Отклонение, -Отклонение).

Обратите внимание на обработку нуля: условие Число < 0 корректно отрабатывает и для нуля — он попадает в ветку Иначе и возвращается как есть. Специальная проверка на ноль не нужна.

Сравнение способов

Макс(Число, -Число)

Одна строка, удобно внутри выражений. Минус — менее очевидно для читающего код без комментария.

Условный оператор Если

Наглядно и легко расширяется. Минус — больше строк, требует отдельной функции для повторного использования.

ВЫБОР в запросе

Единственный прямой способ в языке запросов. Не применим в коде модулей.

Модуль числа в языке запросов 1С

В запросах функции Макс() и Мин() работают как агрегатные по группе записей, поэтому трюк с Макс(Поле, -Поле) там неприменим. Для вычисления модуля по каждой строке используется конструкция ВЫБОР:

ВЫБРАТЬ

Товары.Количество КАК Количество,

ВЫБОР

КОГДА Товары.Количество < 0

ТОГДА -Товары.Количество

ИНАЧЕ Товары.Количество

КОНЕЦ КАК КоличествоПоМодулю

ИЗ

Документ.Инвентаризация.Товары КАК Товары

Та же конструкция применяется в вычисляемых полях СКД и в произвольных выражениях отборов, где допустим язык выражений запросов. Это стандартный приём при построении отчётов по расхождениям: например, когда нужно показать величину отклонения факта от плана без знака.

Модуль в условии отбора

Если нужно отобрать записи, у которых отклонение по модулю превышает порог, условие пишут через ИЛИ, чтобы не вычислять ВЫБОР дважды:

ГДЕ

(Товары.Отклонение > &Порог

ИЛИ Товары.Отклонение < -&Порог)

Такой вариант обычно работает быстрее, чем сравнение результата ВЫБОР с порогом, поскольку даёт оптимизатору запросов более простое условие.

Проверка результата и краевые случаи

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

Особое внимание — типам данных. Если значение приходит из реквизита с типом «Строка» (например, загружено из файла), перед вычислением его нужно преобразовать: Число(СтроковоеЗначение). Иначе операция смены знака вызовет ошибку преобразования типов.

Для значений, которые могут быть NULL (в запросах при левых соединениях), модуль через ВЫБОР без обработки NULL вернёт NULL: условие NULL < 0 не выполняется, но и ветка ИНАЧЕ вернёт NULL. Если нужен ноль вместо NULL, оберните поле в ЕСТЬNULL(Поле, 0).

Контрольные точки

Как проверить результат

Положительное число 10
Норма

Результат 10, знак не меняется

Тревожный признак

Результат -10 или ошибка

Отрицательное число -7,5
Норма

Результат 7,5

Тревожный признак

Результат остался отрицательным

Ноль
Норма

Результат 0 без ошибок

Тревожный признак

Ошибка или неожиданное значение

NULL в запросе
Норма

Обработан через ЕСТЬNULL или осознанно оставлен NULL

Тревожный признак

Пустые строки в отчёте там, где ожидался ноль

Типичные ошибки при вычислении модуля

Первая и самая распространённая ошибка — попытка вызвать несуществующую функцию Abs() или Модуль(). Код не компилируется, и на поиск причины уходит время, если разработчик не знает об отсутствии такой функции в платформе.

Вторая ошибка — применение Макс(Поле, -Поле) в языке запросов. Здесь Макс() агрегатная, и запрос либо вернёт ошибку, либо, что хуже, неожиданный результат в группировке. В запросах работает только ВЫБОР.

Третья группа ошибок связана с данными: попытка взять модуль от строки без преобразования, игнорирование NULL в соединениях и потеря точности при работе с числами большой разрядности. Все они проявляются не в момент написания кода, а на реальных данных, поэтому тестирование на реальных документах обязательно.

Типичные ошибки
01
Вызов Abs() — функции нет в платформе, код не компилируется; используйте Макс() или условие
02
Макс(Поле, -Поле) в запросе — там Макс() агрегатная; применяйте ВЫБОР КОГДА
03
Модуль от строки без Число() — ошибка преобразования типов на реальных данных
04
Игнорирование NULL после левого соединения — пустые значения вместо чисел в отчёте

Когда задачу стоит решать иначе

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

Если модуль нужен только для сортировки (показать сначала самые большие отклонения независимо от знака), вычисление можно выполнить один раз в запросе и упорядочить по вычисленному полю — это прозрачнее, чем сортировка на клиенте после выборки.

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

Итог

Что важно запомнить

Функции Abs() в 1С нет. В коде модулей модуль получают через Макс(Число, -Число) или условие Если Число < 0. В запросах и СКД — через ВЫБОР КОГДА Поле < 0 ТОГДА -Поле ИНАЧЕ Поле КОНЕЦ. Перед вычислением проверяйте тип данных и обрабатывайте NULL.

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

Есть ли в 1С встроенная функция модуля числа?

Нет, функции Abs() или Модуль() во встроенном языке платформы не существует. Абсолютное значение вычисляют через Макс(Число, -Число), условный оператор или конструкцию ВЫБОР в запросах.

Как получить модуль числа в запросе 1С?

Используйте конструкцию ВЫБОР КОГДА Поле < 0 ТОГДА -Поле ИНАЧЕ Поле КОНЕЦ. Функция Макс() в запросах агрегатная и для этой цели не подходит.

Работает ли Макс(Число, -Число) с дробными и отрицательными значениями?

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

Что делать, если поле в запросе может быть NULL?

Оберните поле в ЕСТЬNULL(Поле, 0) до вычисления модуля. Иначе для NULL-значений конструкция ВЫБОР вернёт NULL, и в отчёте появятся пустые ячейки вместо чисел.

Можно ли вычислить модуль в вычисляемом поле СКД?

Да, в выражении вычисляемого поля используется тот же синтаксис ВЫБОР, что и в языке запросов: ВЫБОР КОГДА Поле < 0 ТОГДА -Поле ИНАЧЕ Поле КОНЕЦ.

Как отобрать записи, где отклонение по модулю больше порога?

Проще всего условием через ИЛИ: ГДЕ Поле > &Порог ИЛИ Поле < -&Порог. Это избавляет от вычисления ВЫБОР и обычно эффективнее для оптимизатора запросов.