Как правильно реализовать округление в большую сторону с кратным шагом (до 0.05, 0.10 и т.д.) в 1С

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

В стандартном встроенном языке 1С функция Окр() выполняет математическое округление до ближайшего целого или заданной разрядности (десятые, сотые и т.д.). Однако в торговых операциях и при формировании прайс-листов часто возникает задача округлять цену строго в большую сторону (в пользу предприятия) с кратным шагом — например, до 0.05 или 0.10 денежных единиц.

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

Анализ задачи округления вверх с шагом 0.05

Сформулируем исходные условия. Если установлен шаг округления 0.05, математическое округление для значения 37.22 даст результат 37.20. В то же время бизнес-логика требует получить 37.25.

Проанализируем требуемую логику на примерах:

  1. Значение 37.21 должно округляться до 37.25.
  2. Значение 37.22 должно округляться до 37.25.
  3. Значение 37.25 уже кратно шагу и должно оставаться 37.25.
  4. Значение 37.26 переходит на следующий шаг и округляется до 37.30.

Вариант 1. Компактное выражение с функцией Цел() и тернарным оператором

Наиболее лаконичный способ решения задачи — использование вычисления целой части с помощью функции Цел() и проверка остатка через условие. Для шага 0.05 коэффициентом масштабирования выступает число 20 (так как 1 / 0.05 = 20).

Разберем математическую формулу для шага 0.05:


// Округление в большую сторону до 0.05
Результат = ?(Цел(Цена * 20) / 20 = Цена, Цел(Цена * 20) / 20, (Цел(Цена * 20) + 1) / 20);

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

  1. Умножаем исходное число на 20. Например, 37.22 * 20 = 744.4.
  2. Берем целую часть: Цел(744.4) = 744.
  3. Делим обратно на 20: 744 / 20 = 37.20.
  4. Сравниваем полученное число с исходной ценой. Если они равны — число уже кратно 0.05. Если не равны, прибавляем к целой части 1 и делим на 20: (744 + 1) / 20 = 37.25.

Аналогично, если требуется округлять в большую сторону до шага 0.10, используется коэффициент 10 (так как 1 / 0.10 = 10):


// Округление в большую сторону до 0.10
Результат = ?(Цел(Цена * 10) / 10 = Цена, Цел(Цена * 10) / 10, (Цел(Цена * 10) + 1) / 10);

Вариант 2. Явная логическая функция с проверкой отклонения

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

Рассмотрим пример функции для шага 0.05:


Функция ОкруглитьДо0_05_ВБольшуюСторону(Цена) Экспорт 
    
    Дельта = Окр(Цена, 1) - Цена;
    
    Если Дельта = 0 Тогда 
        // Число уже кратно 0.10
        Результат = Цена;
    ИначеЕсли Дельта < 0 Тогда 
        // Дробные значения 0.01, 0.02, 0.03, 0.04 подтягиваем до 0.05
        Результат = Цена + (0.05 - (Цена - Окр(Цена, 1)));
    ИначеЕсли Дельта = 0.05 Тогда 
        // Уже кратно 0.05
        Результат = Цена;
    Иначе 
        // Для значений выше 0.05 подтягиваем до следующего десятичного разряда
        Результат = Окр(Цена, 1);
    КонецЕсли;
    
    Возврат Результат;
КонецФункции

Вариант 3. Универсальная функция округления вверх с произвольным шагом

В реальных проектах шаг округления может меняться (например, 0.05, 0.10, 0.50, 5.00 или 10.00). Для таких задач целесообразно написать универсальную функцию, принимающую два параметра: исходную сумму и желаемый шаг.

Проанализируем следующий универсальный алгоритм:


Функция ОкруглитьВБольшуюСторону(Значение, Шаг) Экспорт
    
    Если Шаг = 0 Тогда
        Возврат Значение;
    КонецЕсли;
    
    // Рассчитываем частное и ограничиваем точность для предотвращения ошибок с плавающей точкой
    Частное = Окр(Значение / Шаг, 6);
    ЦелоеЧастное = Цел(Частное);
    
    // Если остатка нет — значение уже кратно шагу, иначе добавляем 1 шаг
    Если ЦелоеЧастное = Частное Тогда
        Возврат Значение;
    Иначе
        Возврат (ЦелоеЧастное + 1) * Шаг;
    КонецЕсли;

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

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

Результат = Цел(Цена / Шаг + 0.999999) * Шаг;

Вариант 4. Округление в большую сторону в запросах 1С

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

Рассмотрим пример запроса с округлением цены вверх до 0.05 (умножаем на 20, округляем вверх, затем делим на 20):


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

Использование встроенных механизмов конфигураций 1С

Если задача связана с формированием прайс-листов и расчетных цен в типовых решениях (1С:Управление торговлей, 1С:ERP, 1С:Комплексная автоматизация), доработка кода часто не требуется.

Разберем порядок настройки в пользовательском режиме:

  1. Перейдем в справочник Виды цен.
  2. Выберем нужный вид цены и откроем настройки округления.
  3. Установим Порядок округления (например, 0.05 или 0.10).
  4. Укажем вариант округления: В большую сторону (или В пользу предприятия).

При расчете цен по формулам или при загрузке новых цен система применит указанное правило автоматически.

Важные особенности и подводные камни

При реализации собственных алгоритмов округления в 1С обратите внимание на следующие нюансы:

1. Погрешность вычислений с плавающей точкой: Из-за особенностей представления двоичных чисел в памяти результат деления 37.25 / 0.05 может составить 745.0000000000001. В результате прямое сравнение ЦелоеЧастное = Частное может вернуть Ложь. Чтобы избежать этой проблемы, всегда предварительно ограничивайте точность деления через Окр(Значение / Шаг, 6).

2. Округление цен и сумм весовых товаров: Округление цены до 0.05 не гарантирует, что итоговая сумма строки документа будет кратна 0.05, если количество товара выражено дробным числом (например, 1.337 кг). В таких случаях алгоритм округления необходимо применять не только к цене номенклатуры, но и пересчитывать итоговую сумму строки или документа.

← На главную