При разработке алгоритмов расчета цен, скидок, налогов или распределения сумм программисты 1С часто сталкиваются с задачей: необходимо округлить число не по стандартным математическим правилам, а всегда в большую сторону (функция «потолок», или Ceil). Нередко попытка использовать для этого встроенную функцию Окр() приводит к недоумению, когда число вроде 6453.33 не превращается в 6453.34. Разберем подробнее, почему так происходит и как правильно реализовать округление вверх в платформе 1С:Предприятие.
Проанализируем частую ошибку: разработчики пытаются вызвать функцию с третьим параметром режима округления, например Окр(6453.33, 2, 1), ожидая округления вверх. Однако число остается неизменным — 6453.33.
Выясним причину такого поведения. В платформе 1С:Предприятие синтаксис функции выглядит следующим образом: Окр(Число, Разрядность, РежимОкругления). Третий параметр принимает значения системного перечисления РежимОкругления (Окр15как20 или Окр15как10, либо числовые эквиваленты 1 и 0). Этот параметр управляет исключительно правилом округления пограничной цифры 5 в младшем разряде:
1 (РежимОкругления.Окр15как20) число 1.5 округлится до 2.0 (РежимОкругления.Окр15как10) число 1.5 округлится до 1.На любые другие цифры (включая единицы, тройки, семерки) данный параметр не оказывает никакого влияния. Если после сотых долей ничего нет, функция Окр() оставит число как есть. Встроенного аналога математической функции Ceil() в глобальном контексте платформы 1С нет, поэтому округление вверх необходимо реализовывать программно.
Посмотрим на постановку задачи: если у вас на входе уже есть число с двумя знаками после запятой (например, 6453.33), и бизнес-логика требует безусловно перейти к следующей сотой доле, округление здесь формально не требуется — достаточно выполнить обычное арифметическое сложение:
Результат = ИсходноеЧисло + 0.01;
Однако чаще всего на практике такая задача возникает, когда в результате деления или вычислений получается число с длинной дробной частью (например, 6453.333333...), и его требуется подтянуть к 6453.34. В таком случае простое прибавление одной копейки приведет к искажению данных.
Разберем по шагам классический алгоритм округления вверх для положительных чисел. Если у числа есть хоть какой-то остаток за пределами второго знака после запятой, мы должны увеличить разряд сотых на единицу. Если же число точно делится до сотых (например, 6453.30), оно должно остаться без изменений.
Для компактной записи в одну строку можно использовать тернарный оператор ?():
Результат = ?(ИсходноеЧисло * 100 = Цел(ИсходноеЧисло * 100), ИсходноеЧисло, (Цел(ИсходноеЧисло * 100) + 1) / 100);
Рассмотрим, как работает эта формула:
Цел(). Если они равны, значит, знаков после сотых нет, и число возвращается в исходном виде.Цел(), прибавляем единицу к целому числу и делим обратно на 100.Когда требуется округлять числа с произвольной точностью (до целых, десятых или сотых), а также корректно обрабатывать отрицательные значения, рекомендуется вынести логику в отдельную экспортную функцию общего модуля.
Важно помнить: встроенная функция Цел() в 1С выполняет простое усечение (отсечение дробной части по направлению к нулю). Поэтому для отрицательных чисел логика округления вверх отличается от положительных. Посмотрим на реализацию универсальной функции:
Функция ОкруглитьВверх(Знач ИсходноеЧисло, Знач Разрядность = 2) Экспорт
Множитель = Pow(10, Разрядность);
СмещенноеЧисло = ИсходноеЧисло * Множитель;
ЦелаяЧасть = Цел(СмещенноеЧисло);
Если СмещенноеЧисло = ЦелаяЧасть Тогда
Возврат ИсходноеЧисло;
ИначеЕсли ИсходноеЧисло > 0 Тогда
Возврат (ЦелаяЧасть + 1) / Множитель;
Иначе
Возврат ЦелаяЧасть / Множитель;
КонецЕсли;
КонецФункции
Такой подход защищает вычисления от ошибок и дает предсказуемый результат на любых входных данных.
Проанализируем альтернативные ситуации, с которыми можно столкнуться при разработке:
ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 2)) выполняет только математическое округление. Если требуется округлить вверх прямо в запросе, используют конструкцию ВЫБОР КОГДА, вычисляя разницу между исходным числом и его округлением до нужной точности.