Как в запросе 1С реализовать округление до десятков в большую сторону?

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

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

В этой статье мы подробно разберем, почему стандартные методы могут давать ошибки, и рассмотрим несколько надежных способов реализации округления вверх (аналог функции Ceil) до десятков.

Проблема использования оператора ВЫРАЗИТЬ

Разберем ситуацию, с которой начал автор темы. Попытка использовать формулу ВЫРАЗИТЬ((Число + 5) / 10 КАК ЧИСЛО(15, 0)) * 10 кажется логичной, но она спотыкается на «чистых» значениях. Если наше число равно 10, то (10 + 5) / 10 даст 1.5. В зависимости от настроек СУБД и особенностей платформы, ВЫРАЗИТЬ для 1.5 может вернуть 2, и в итоге мы получим 20 вместо ожидаемых 10. Это происходит потому, что 1С использует арифметическое округление, где 0.5 округляется до ближайшего целого (часто до большего, но в некоторых СУБД может применяться «банковское» округление до ближайшего четного).

Проанализируем современные и классические подходы к решению этой задачи.

Решение 1: Использование функции ОКР (для платформы 8.3.20 и выше)

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

Рассмотрим пример кода для округления до десятков в большую сторону:


ВЫБРАТЬ
    ОКР(Турбулентность.Значение, -1, РежимОкругления.Окр15как20) КАК Результат
ИЗ
    Справочник.Номенклатура КАК Турбулентность

Разберем параметры функции:

  1. Число: исходное значение, которое нужно округлить.
  2. Разрядность: значение -1 указывает системе, что округление нужно производить до десятков (соответственно, -2 — до сотен).
  3. Режим округления: константа РежимОкругления.Окр15как20 гарантирует, что любое значение, выходящее за пределы целого десятка, будет округлено вверх.

Решение 2: Математический метод с использованием «дельты»

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

Посмотрим на пример реализации:


ВЫБРАТЬ
    ВЫРАЗИТЬ((НашеЧисло + 4.999999) / 10 - 0.5 КАК ЧИСЛО(15, 0)) * 10 КАК ОкруглениеВверх
ИЗ
    Документ.ЗаказПокупателя КАК Заказ

Важный момент: точность (количество девяток) должна быть выше, чем возможная дробная часть вашего числа. Для сумм в рублях достаточно 3-4 знаков после запятой, но для весовых товаров лучше использовать максимально возможную точность. Однако этот метод все равно считается «костылем», так как он теоретически может привести к ошибке на экстремально малых значениях.

Решение 3: Универсальный метод через ВЫБОР КОГДА

Наиболее надежным способом для старых платформ является проверка остатка. Поскольку в запросах 1С нет оператора % (остаток от деления), мы можем сымитировать его работу, сравнив число с его целой частью после деления на 10.

Проанализируем логику: если число делится на 10 без остатка, оставляем его как есть. В противном случае отбрасываем «хвост» и прибавляем 10. Рассмотрим, как это выглядит в коде:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ВЫРАЗИТЬ(Данные.Цена / 10 - 0.5 КАК ЧИСЛО(15, 0)) * 10 = Данные.Цена
            ТОГДА Данные.Цена
        ИНАЧЕ (ВЫРАЗИТЬ(Данные.Цена / 10 - 0.5 КАК ЧИСЛО(15, 0)) + 1) * 10
    КОНЕЦ КАК ЦенаОкругленная
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Данные

В этом примере конструкция ВЫРАЗИТЬ(Число / 10 - 0.5 КАК ЧИСЛО(15, 0)) эффективно находит целое количество десятков в числе (аналог функции Floor). Этот метод абсолютно точен и не зависит от «количества девяток» в константах.

Решение 4: Округление через систему компоновки данных (СКД)

Если ваша задача — просто вывести округленное значение в отчет, а не использовать его для дальнейших расчетов внутри запроса, мы рекомендуем перенести логику округления в Вычисляемые поля СКД. В СКД доступны функции общего модуля 1С, а также более гибкие механизмы форматирования.

Рассмотрим алгоритм действий в СКД:

  1. Переходим на закладку «Вычисляемые поля».
  2. Добавляем новое поле, в выражении которого пишем: Окр(Цена / 10 + 0.49, 0) * 10.
  3. Или используем функцию общего модуля, если требуется сложная логика: МойОбщийМодуль.ОкруглитьДоДесятковВверх(Цена).

Преимущество этого метода в том, что расчет происходит на сервере приложений 1С, где доступен полный синтаксис встроенного языка, включая Цел() и Окр() с любыми режимами.

Сравнение методов и рекомендации

Подведем итог нашему анализу:

Выяснив причину некорректной работы стандартного ВЫРАЗИТЬ, мы понимаем, что округление в запросах — это всегда работа с границами значений. Будьте внимательны при работе с отрицательными числами, так как «большая сторона» для них может означать как движение к нулю, так и движение к минус бесконечности. В большинстве бизнес-задач (цены, остатки) подразумеваются положительные числа, для которых приведенные выше примеры работают идеально.

← На главную