При расчете цен, скидок, сумм к выплате или параметров логистики разработчикам регулярно приходится решать задачу приведения чисел к определенному шагу (кратности). Например, требуется округлить сумму 183 до ближайшего числа, кратного 5 в большую сторону (получив 185), либо округлить число 192 до 195. Стандартная функция платформы Окр() предназначена только для округления до заданного десятичного разряда, поэтому для произвольной кратности требуется применять специальные формулы и функции.
Разберем подробно все варианты решения этой задачи: от лаконичных математических выражений в одну строку до универсальной функции с поддержкой различных режимов округления.
Проанализируем классический подход к округлению до произвольного шага. Если нам необходимо стандартное математическое (арифметическое) округление до числа, кратного значению Кратность, мы делим исходное число на шаг, выполняем стандартное округление до целого и умножаем обратно на шаг:
Результат = Окр(ИсходноеЧисло / Кратность, 0) * Кратность;
Если же стоит задача округлить число всегда в большую сторону (например, в пользу предприятия), простая прибавка 0.5 вида Окр(Сумма / 5 + 0.5) * 5 содержит скрытую ошибку: число, которое уже кратно 5 (например, 190), превратится в 195. Чтобы избежать этого, перед округлением необходимо проверять кратность либо использовать функцию Цел() с вычитанием минимальной погрешности.
Рассмотрим лаконичную формулу, которая позволяет округлить положительное число строго вверх до нужного шага без ветвлений Если ... Тогда:
Результат = Цел((ИсходноеЧисло + Кратность - 0.000000001) / Кратность) * Кратность;
Посмотрим на логику работы формулы:
183, а кратность 5: Цел((183 + 5 - 0.000000001) / 5) * 5 = Цел(187.999999999 / 5) * 5 = Цел(37.5999999) * 5 = 37 * 5 = 185.190): Цел((190 + 5 - 0.000000001) / 5) * 5 = Цел(194.999999999 / 5) * 5 = Цел(38.9999999) * 5 = 38 * 5 = 190. Число остается неизменным.Для создания гибкого и читаемого кода в модулях конфигурации рекомендуется использовать универсальную функцию. Она обрабатывает четыре основных режима: математическое округление (с направлением 0.5 вверх или вниз), округление строго вниз (в пользу покупателя) и строго вверх (в пользу продавца).
Разберем реализацию функции:
Функция ОкруглитьДоКратности(ИсходноеЧисло, РазрядОкругления = 1, РежимОкругления = 1) Экспорт
// Если число уже кратно шагу, возвращаем его без изменений
ОстатокОтДеления = ИсходноеЧисло % РазрядОкругления;
Если ОстатокОтДеления = 0 Тогда
Возврат ИсходноеЧисло;
КонецЕсли;
Если РежимОкругления = 1 Тогда
// Обычный по математическим правилам (0.5 вверх)
Результат = ИсходноеЧисло - ?(ОстатокОтДеления >= (РазрядОкругления / 2), -РазрядОкругления + ОстатокОтДеления, ОстатокОтДеления);
ИначеЕсли РежимОкругления = 2 Тогда
// Обычный по математическим правилам (0.5 вниз)
Результат = ИсходноеЧисло - ?(ОстатокОтДеления > (РазрядОкругления / 2), -РазрядОкругления + ОстатокОтДеления, ОстатокОтДеления);
ИначеЕсли РежимОкругления = 3 Тогда
// Всегда в меньшую сторону (к полу)
Результат = ИсходноеЧисло - ОстатокОтДеления;
ИначеЕсли РежимОкругления = 4 Тогда
// Всегда в большую сторону (к потолку)
Результат = ИсходноеЧисло - ОстатокОтДеления + РазрядОкругления;
КонецЕсли;
Возврат Результат;
КонецФункции
Посмотрим на примеры вызова данной функции:
// Округление вверх до 5: возвращает 185
Сумма1 = ОкруглитьДоКратности(183, 5, 4);
// Округление вверх уже кратного числа: возвращает 190
Сумма2 = ОкруглитьДоКратности(190, 5, 4);
// Округление вниз до 10: возвращает 190
Сумма3 = ОкруглитьДоКратности(197, 10, 3);
В языке запросов платформы 1С оператор взятия остатка от деления % и функция Цел() отсутствуют. Приведение к целому через ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 0)) выполняет стандартное арифметическое округление. Для вычисления кратности вверх в запросе применяется конструкция ВЫБОР КОГДА:
ВЫБОР
КОГДА Таблица.Сумма / &Кратность = ВЫРАЗИТЬ(Таблица.Сумма / &Кратность КАК ЧИСЛО(15, 0))
ТОГДА Таблица.Сумма
КОГДА Таблица.Сумма / &Кратность > ВЫРАЗИТЬ(Таблица.Сумма / &Кратность КАК ЧИСЛО(15, 0))
ТОГДА (ВЫРАЗИТЬ(Таблица.Сумма / &Кратность КАК ЧИСЛО(15, 0)) + 1) * &Кратность
ИНАЧЕ (ВЫРАЗИТЬ(Таблица.Сумма / &Кратность КАК ЧИСЛО(15, 0))) * &Кратность
КОНЕЦ
Цел() в платформе 1С отбрасывает дробную часть по направлению к нулю (Цел(-1.8) = -1). Если в расчетах могут появиться отрицательные числа (например, корректировки или скидки), округление следует производить по модулю через функцию Abs() / Число < 0, либо явно контролировать знак.