В практике программирования на платформе 1С:Предприятие часто возникает задача приведения денежных сумм или количественных показателей к определенной кратности. Одной из самых популярных задач является округление «всегда в большую сторону» до ближайшего числа, кратного пяти (например, 122 превращается в 125, а 126 — в 130). Стандартная функция Окр() не всегда справляется с этой задачей напрямую, так как она ориентирована на арифметическое округление до знаков после запятой.
В этой статье мы подробно разберем несколько эффективных способов реализации такой логики: от простых математических формул до универсальных функций, учитывающих отрицательные числа и работу в запросах.
Проанализируем самый наглядный метод, основанный на вычислении остатка. Логика проста: если число уже кратно 5, оставляем его как есть. Если нет — выясняем, сколько не хватает до следующей «пятерки», и добавляем эту разницу.
Рассмотрим пример кода:
ИсходноеЧисло = 126; // Результат должен быть 130
ОстатокОтДеленияНа5 = ИсходноеЧисло % 5;
ОкругленноеЧисло = ?(ОстатокОтДеленияНа5 = 0, ИсходноеЧисло, ИсходноеЧисло + 5 - ОстатокОтДеленияНа5);
Этот метод хорош тем, что он максимально понятен при чтении кода. Однако стоит помнить, что оператор % (остаток от деления) в 1С может вести себя специфически с отрицательными числами.
Теперь разберем более лаконичный вариант, который часто применяется опытными разработчиками для минимизации условий Если или тернарных операторов. Мы можем использовать деление на кратность с последующим увеличением результата.
Посмотрим на формулу для положительных чисел:
// Вариант для целых чисел
Результат = ЦЕЛ(Сумма / 5 + 0.8) * 5;
// Вариант с высокой точностью (учитывает копейки)
Результат = ЦЕЛ(Сумма / 5 + 0.9999999999) * 5;
Как это работает? Мы делим число на 5, прибавляем «коэффициент смещения» и отсекаем дробную часть функцией Цел(). Если число было равно 10, то 10/5 = 2. Прибавляем 0.999, получаем 2.999, целая часть остается 2. 2 * 5 = 10. Если же было 11, то 11/5 = 2.2. Прибавляем 0.999, получаем 3.199, целая часть становится 3. 3 * 5 = 15. Мы достигли цели — округления вверх.
Выясним, как сделать код более надежным, если могут встретиться отрицательные значения или дробная кратность (например, нужно округлить до 0.5 или до 25). Для этого лучше оформить логику в отдельную функцию.
Проанализируем следующий алгоритм:
Функция ОкруглитьДоКратногоВБольшуюСторону(Значение, Кратность) Экспорт
Если Кратность = 0 Тогда
Возврат Значение;
КонецЕсли;
Остаток = Значение % Кратность;
Если Остаток = 0 Тогда
Возврат Значение;
ИначеЕсли Значение > 0 Тогда
Возврат Значение + (Кратность - Остаток);
Иначе
// Для отрицательных чисел "в большую сторону" означает ближе к нулю
Возврат Значение - Остаток;
КонецЕсли;
КонецФункции
Важно различать математическое увеличение (в сторону плюс бесконечности) и увеличение по модулю. Данная функция реализует именно математическое увеличение.
Ситуация усложняется, когда округление нужно выполнить прямо в тексте запроса. В языке запросов 1С нет оператора остатка от деления и функции Окр() с нужными нам параметрами. Однако мы можем использовать комбинацию ВЫРАЗИТЬ и ЦЕЛ.
Рассмотрим пример конструкции в запросе:
ВЫБРАТЬ
(ВЫРАЗИТЬ(Сумма / 5 - 0.5 КАК ЧИСЛО(15, 0)) + 1) * 5 КАК ОкругленнаяСуммаВверх
ИЗ
РегистрНакопления.Продажи
Здесь используется особенность функции ВЫРАЗИТЬ( ... КАК ЧИСЛО), которая выполняет округление. Чтобы гарантировать округление вверх, мы манипулируем вычитанием 0.5 и прибавлением единицы. Однако более точным и современным способом для запросов считается использование ВЫБОР КОГДА:
ВЫБРАТЬ
ВЫБОР
КОГДА Сумма / 5 = ЦЕЛ(Сумма / 5) ТОГДА Сумма
ИНАЧЕ (ЦЕЛ(Сумма / 5) + 1) * 5
КОНЕЦ КАК СуммаКратно5
Мало кто знает, что встроенная функция Окр() в 1С v8 имеет третий параметр — РежимОкругления. Хотя напрямую «до 5» она не округляет, мы можем скомбинировать её с масштабированием.
Посмотрим на этот изящный метод:
// Используем режим Окр15как20 для имитации округления вверх
Результат = Окр(ИсходноеЧисло / 5 + 0.49, 0, РежимОкругления.Окр15как10) * 5;
Этот подход опирается на стандартные механизмы платформы и обычно работает быстрее, чем сложные условия Если...Тогда.
Если вы работаете в конфигурациях на базе БСП (например, 1С:ERP, УТ 11 или БП 3.0), прежде чем писать свой велосипед, загляните в общие модули. Проанализируем возможности системы:
ЦенообразованиеКлиентСервер.ОкруглитьЦену(). Она уже умеет округлять суммы по различным правилам.0.999.... При необходимости провести анализ наценки на закупочные цены в УТ 11, КА 2 или БП, убедитесь, что формулы учитывают особенности представления чисел с плавающей точкой.Подводя итог, можно сказать, что выбор метода зависит от контекста. Для простых вычислений в коде используйте остаток от деления. Для запросов — математическую формулу с ЦЕЛ(). А чтобы избежать финансовых расхождений, применяйте подбор цен для получения суммы НДС без округления, что значительно упростит расчеты и уменьшит число инцидентов с клиентами.