Как правильно реализовать округление вверх в запросе 1С

Программист 1С v8.3 (Управляемые формы)
← На главную

При разработке алгоритмов заказа товаров часто возникает задача округления расчетного количества до целых упаковок (тарности). В языке запросов 1С нет встроенных функций ОКРВВЕРХ или CEIL, что заставляет разработчиков прибегать к использованию конструкции ВЫБОР или математических хитростей с оператором ВЫРАЗИТЬ. В этой статье мы подробно разберем, как работает округление в запросах, почему стандартные условия могут не срабатывать и как написать надежный код для расчета заказов.

Анализ работы оператора ВЫРАЗИТЬ

Прежде всего, нам необходимо прояснить, как именно система 1С обрабатывает числа при использовании оператора ВЫРАЗИТЬ. В отличие от некоторых заблуждений, этот оператор не просто отсекает дробную часть, а выполняет полноценное арифметическое округление.

Рассмотрим по шагам правила округления в запросе:

  1. Если дробная часть числа меньше 0.5, число округляется в меньшую сторону (до ближайшего целого).
  2. Если дробная часть равна или больше 0.5, число округляется в большую сторону.
  3. Это поведение отличается от функции Окр() во встроенном языке, где по умолчанию используется «бухгалтерское» округление (до ближайшего четного). В запросах же 0.5 всегда превращается в 1.

Посмотрим на пример, подтверждающий это поведение в консоли запросов:


ВЫБРАТЬ
    ВЫРАЗИТЬ(0.5 КАК ЧИСЛО(10, 0)) КАК Поле1,
    ВЫРАЗИТЬ(0.49 КАК ЧИСЛО(10, 0)) КАК Поле2,
    ВЫРАЗИТЬ(20 / 3 КАК ЧИСЛО(10, 0)) КАК Поле3

Результатом выполнения такого запроса будут значения: 1, 0 и 7 соответственно. Это фундаментальное знание, которое поможет нам строить дальнейшую логику.

Разбор проблемы нецелых чисел в условиях

Часто программисты сталкиваются с ситуацией, когда конструкция ВЫБОР работает некорректно. Проанализируем типичный пример: нам нужно заказать товар так, чтобы общее количество было кратно Тарность. Мы пытаемся сравнить результат деления с его округленным вариантом.

Выясним причину возможной ошибки. Если переменная Рекомендовано (количество к заказу) или Тарность сами по себе являются дробными числами (например, вес в кг), то простое сравнение может не сработать. Если Рекомендовано равно 10.1, а Тарность равна 1, то результат деления будет 10.1. Оператор ВЫРАЗИТЬ(10.1 КАК ЧИСЛО(15, 0)) даст 10. Условие 10 >= 10.1 вернет Ложь, и мы уйдем в ветку ИНАЧЕ, прибавляя лишнюю единицу там, где это не планировалось, или наоборот.

Для корректной работы условий всегда проверяйте типы данных в исходных таблицах. Если вы работаете с результатами предыдущих пакетов запроса, убедитесь, что значения были правильно типизированы через ВЫРАЗИТЬ еще на этапе формирования временной таблицы.

Реализация алгоритма округления «вверх»

Рассмотрим наиболее надежный способ реализации округления вверх (до целого количества упаковок) в запросе. Нам нужно получить такое число Заказать, которое будет кратно Тарность и будет не меньше, чем Рекомендовано.

Проанализируем универсальную конструкцию:


ВЫБОР
    КОГДА ТаблицаСЗаказом.Тарность > 0
        ТОГДА ВЫБОР
            // Проверяем, является ли число уже кратным тарности
            КОГДА ВЫРАЗИТЬ(ТаблицаСЗаказом.Рекомендовано / ТаблицаСЗаказом.Тарность КАК ЧИСЛО(15, 0)) 
                  >= ТаблицаСЗаказом.Рекомендовано / ТаблицаСЗаказом.Тарность
                // Если округленное значение больше или равно исходному, значит арифметическое округление сработало вверх или в ноль
                ТОГДА ТаблицаСЗаказом.Тарность * (ВЫРАЗИТЬ(ТаблицаСЗаказом.Рекомендовано / ТаблицаСЗаказом.Тарность КАК ЧИСЛО(15, 0)))
            ИНАЧЕ 
                // Если арифметическое округление сработало вниз, принудительно прибавляем единицу
                ТаблицаСЗаказом.Тарность * (ВЫРАЗИТЬ(ТаблицаСЗаказом.Рекомендовано / ТаблицаСЗаказом.Тарность КАК ЧИСЛО(15, 0)) + 1)
        КОНЕЦ
    ИНАЧЕ ТаблицаСЗаказом.Рекомендовано
КОНЕЦ КАК Заказать

Существует и более лаконичный «математический» способ округления вверх для положительных чисел. Мы можем прибавить к числу 0.4999999999 перед выполнением ВЫРАЗИТЬ. Это заставит любое число с минимальной дробной частью перейти порог 0.5 и округлиться вверх.

Пример лаконичного кода:

ВЫРАЗИТЬ(Таблица.Значение + 0.4999999999 КАК ЧИСЛО(15, 0))

Однако будьте осторожны: количество девяток после запятой определяет точность, с которой система будет считать число «почти целым». Если в ваших данных возможны значения с 6 знаками после запятой (например, 1.000001), такой метод может потребовать еще большей точности.

Важные нюансы: NULL и Деление на ноль

При расчетах в запросах мы всегда должны помнить о безопасности вычислений. Разберем основные риски:

  1. Значения NULL: Если поле Тарность или Рекомендовано содержит NULL, результатом всего арифметического выражения будет NULL. Обязательно используйте функцию ЕСТЬNULL(Поле, 0).
  2. Деление на ноль: Если после применения ЕСТЬNULL в поле Тарность оказался ноль, запрос завершится аварийно. Всегда оборачивайте деление в конструкцию ВЫБОР КОГДА Тарность > 0.
  3. Точность хранения: При делении в SQL Server результат часто имеет 6 знаков после запятой. Если вы сравниваете два результата деления, они могут незначительно отличаться в 6-м знаке (эффект «плавающей точки»). В критичных местах лучше явно ограничивать точность обеих сторон сравнения через ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 3)).

Итоги и рекомендации

Мы выяснили, что основной причиной ошибок при округлении в запросах является неучтенная дробная часть исходных данных или непонимание принципа работы ВЫРАЗИТЬ. Для создания стабильного отчета или обработки заказов рекомендуем придерживаться следующих правил:

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

← На главную