В процессе разработки на платформе 1С:Предприятие программисты часто сталкиваются с задачей округления чисел. Стандартная функция Окр() работает по правилам арифметического округления, однако в бизнес-логике (например, при расчете количества упаковок или целых дней) часто требуется округление «вверх» до ближайшего целого. В математике такая функция называется Ceil. Давайте подробно разберем, как реализовать этот механизм, используя стандартные инструменты встроенного языка.
Самый наглядный и понятный способ заключается в проверке: имеет ли число дробную часть. Если число уже является целым, мы оставляем его как есть. Если же у числа есть любая дробная часть (даже 0.001), мы отбрасываем ее и прибавляем к результату единицу.
Рассмотрим пример кода, реализующий эту логику:
ЧислоДляОкругления = 9.2;
Результат = ?(Цел(ЧислоДляОкругления) = ЧислоДляОкругления, ЧислоДляОкругления, Цел(ЧислоДляОкругления) + 1);
// Результат будет равен 10
Проанализируем, как это работает по шагам:
Цел() отсекает дробную часть, оставляя только целое число.Существует более элегантный и производительный метод, который часто называют «программным трюком». Он основан на свойстве функции Цел() при работе с отрицательными числами. Этот метод работает быстрее, так как не содержит логических ветвлений (условий).
Разберем пример реализации:
ЧислоДляОкругления = 10.03;
Результат = -Цел(-ЧислоДляОкругления);
// Результат будет равен 11
Давайте посмотрим, как это происходит внутри системы:
Цел(). Для отрицательных чисел она отсекает дробную часть, превращая -10.03 в -10 (в некоторых версиях/ситуациях) или, следуя строгой математической логике платформы, возвращает ближайшее целое в сторону нуля.Цел(). Поэтому Цел(-10.03) даст -10. Чтобы этот метод корректно работал как «Ceil», нужно убедиться в поведении платформы. На практике в 1С для положительных чисел этот метод часто заменяют на формулу выше.Мало кто знает, что встроенная функция Окр() имеет третий параметр, который определяет режим округления. Рассмотрим возможность использования смещения вместе с системным округлением.
Посмотрим на пример:
ЧислоДляОкругления = 9.2;
// Прибавляем 0.5 и используем режим округления 1.5 до 1 (Окр15Как10)
Результат = Окр(ЧислоДляОкругления + 0.4999999999, 0, РежимОкругления.Окр15Как10);
Однако более надежным способом с использованием Окр() является вариант, предложенный опытными разработчиками:
ЧислоДляОкругления = 9.009;
Результат = Окр(ЧислоДляОкругления + 0.5, 0, 0);
Важное замечание: Метод с прибавлением 0.5 или 0.49 опасен тем, что при очень малых дробных частях (например, 9.000000001) он может не сработать или дать неверный результат из-за точности вычислений. Поэтому использование тернарного оператора из первого способа считается более «безопасным» для бизнес-приложений.
Еще один способ проверить наличие дробной части — использовать оператор получения остатка %. Если остаток от деления на 1 больше нуля, значит, у числа есть «хвост», который нужно округлить вверх.
Разберем ситуацию:
Число = 10.03;
Результат = Цел(Число) + ?(Число % 1 > 0, 1, 0);
Этот метод очень удобен и нагляден: мы явно говорим системе «если есть хоть какой-то остаток, добавь единицу к целому».
Нужно учитывать, что «округление вверх» для отрицательных чисел может трактоваться двояко:
Если ваша задача требует округления по модулю (всегда в сторону увеличения абсолютного значения), то используйте следующий подход:
Если Число < 0 Тогда
Результат = - (Цел(Abs(Число)) + ?(Abs(Число) % 1 > 0, 1, 0));
Иначе
Результат = Цел(Число) + ?(Число % 1 > 0, 1, 0);
КонецЕсли;
Выясним причину, по которой иногда округление может давать странные результаты. В 1С, как и во многих языках программирования, числа могут храниться с микроскопической погрешностью (например, 9 вместо 9.000000000000001). В этом случае обычная проверка Цел(ч) = ч может выдать Ложь.
Рекомендация: Перед выполнением логики округления «вверх», предварительно округлите число до большого количества знаков (например, до 8), чтобы убрать возможные «шумы» вычислений:
ЧислоПодготовленное = Окр(ИсходноеЧисло, 8);
Результат = ?(Цел(ЧислоПодготовленное) = ЧислоПодготовленное, ЧислоПодготовленное, Цел(ЧислоПодготовленное) + 1);
Подводя итог, можно сказать, что наиболее универсальным и читаемым способом для программиста 1С является использование конструкции с Цел() и тернарным оператором ?(). Это гарантирует предсказуемое поведение системы и легкость отладки кода.