Разработка и Конфигурация · 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 или ошибка
Результат 7,5
Результат остался отрицательным
Результат 0 без ошибок
Ошибка или неожиданное значение
Обработан через ЕСТЬNULL или осознанно оставлен NULL
Пустые строки в отчёте там, где ожидался ноль
Типичные ошибки при вычислении модуля
Первая и самая распространённая ошибка — попытка вызвать несуществующую функцию Abs() или Модуль(). Код не компилируется, и на поиск причины уходит время, если разработчик не знает об отсутствии такой функции в платформе.
Вторая ошибка — применение Макс(Поле, -Поле) в языке запросов. Здесь Макс() агрегатная, и запрос либо вернёт ошибку, либо, что хуже, неожиданный результат в группировке. В запросах работает только ВЫБОР.
Третья группа ошибок связана с данными: попытка взять модуль от строки без преобразования, игнорирование NULL в соединениях и потеря точности при работе с числами большой разрядности. Все они проявляются не в момент написания кода, а на реальных данных, поэтому тестирование на реальных документах обязательно.
Когда задачу стоит решать иначе
Иногда потребность в модуле — симптом того, что данные хранятся неоптимально. Например, если приходится постоянно вычислять модуль разницы между двумя суммами в отчётах, возможно, стоит хранить отклонение отдельным вычисляемым реквизитом или ресурсом регистра.
Если модуль нужен только для сортировки (показать сначала самые большие отклонения независимо от знака), вычисление можно выполнить один раз в запросе и упорядочить по вычисленному полю — это прозрачнее, чем сортировка на клиенте после выборки.
Для массовых расчётов в коде, где модуль используется десятки раз, вынос логики в отдельную функцию общего модуля снижает риск расхождений: исправление в одном месте автоматически применится везде.
Что важно запомнить
Функции Abs() в 1С нет. В коде модулей модуль получают через Макс(Число, -Число) или условие Если Число < 0. В запросах и СКД — через ВЫБОР КОГДА Поле < 0 ТОГДА -Поле ИНАЧЕ Поле КОНЕЦ. Перед вычислением проверяйте тип данных и обрабатывайте NULL.
Частые вопросы
Есть ли в 1С встроенная функция модуля числа?
Нет, функции Abs() или Модуль() во встроенном языке платформы не существует. Абсолютное значение вычисляют через Макс(Число, -Число), условный оператор или конструкцию ВЫБОР в запросах.
Как получить модуль числа в запросе 1С?
Используйте конструкцию ВЫБОР КОГДА Поле < 0 ТОГДА -Поле ИНАЧЕ Поле КОНЕЦ. Функция Макс() в запросах агрегатная и для этой цели не подходит.
Работает ли Макс(Число, -Число) с дробными и отрицательными значениями?
Да, приём корректен для любых чисел: положительных, отрицательных, дробных и нуля. Ограничение одно — значение должно быть числового типа, строку нужно предварительно преобразовать через Число().
Что делать, если поле в запросе может быть NULL?
Оберните поле в ЕСТЬNULL(Поле, 0) до вычисления модуля. Иначе для NULL-значений конструкция ВЫБОР вернёт NULL, и в отчёте появятся пустые ячейки вместо чисел.
Можно ли вычислить модуль в вычисляемом поле СКД?
Да, в выражении вычисляемого поля используется тот же синтаксис ВЫБОР, что и в языке запросов: ВЫБОР КОГДА Поле < 0 ТОГДА -Поле ИНАЧЕ Поле КОНЕЦ.
Как отобрать записи, где отклонение по модулю больше порога?
Проще всего условием через ИЛИ: ГДЕ Поле > &Порог ИЛИ Поле < -&Порог. Это избавляет от вычисления ВЫБОР и обычно эффективнее для оптимизатора запросов.