Как в 1С округлить число в меньшую сторону или просто отбросить лишние знаки после запятой?

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

В практике разработчика 1С часто возникает задача не просто округлить число по правилам математики, а именно «отсечь» лишние знаки. Например, когда из числа 7 167,127 нам нужно получить строго 7 167,12. Стандартная функция Окр() в большинстве своих режимов при значении 7 в третьем знаке округлит число в большую сторону до 13 копеек. В этой статье мы подробно разберем, как реализовать «округление вниз» (или отбрасывание разрядов) различными способами, проанализируем нюансы работы с отрицательными числами и особенности вычислений в запросах.

Способ 1: Использование функции Цел()

Самый популярный и простой способ, предложенный в обсуждении, — это использование функции Цел() (получение целой части числа). Поскольку нам нужно сохранить два знака после запятой, мы сначала «поднимаем» эти знаки в целую часть, а затем возвращаем их обратно.

Разберем этот алгоритм по шагам:

  1. Умножаем исходное число на 100 (если нужно 2 знака) или на 10, 1000 и т.д. в зависимости от требуемой точности.
  2. Применяем функцию Цел(), которая просто отбрасывает всю дробную часть.
  3. Делим результат обратно на тот же множитель.

Посмотрим на пример кода:


ИсходноеЧисло = 7167.127;
Результат = Цел(ИсходноеЧисло * 100) / 100;
// Результат будет равен 7167.12

Удобно тестировать подобные математические алгоритмы в режиме предприятия, используя встраиваемую консоль кода на основе Monaco-editor.

Важный нюанс: Этот метод отлично работает для положительных чисел, выполняя так называемое «округление к нулю» (Truncate). Однако, если мы столкнемся с отрицательным числом, например -7 167,127, результат будет -7 167,12. С точки зрения строгой математики (функция Floor), округление вниз для отрицательного числа должно давать -7 167,13, так как это число меньше. Если ваша задача требует именно математического «вниз», этот код придется дополнить проверкой знака.

Способ 2: Математическое смещение через функцию Окр()

Некоторые разработчики предпочитают использовать стандартную функцию Окр(), но со специальным «сдвигом». Идея заключается в том, чтобы вычесть из числа половину значения разряда, до которого происходит округление. Для округления до двух знаков это 0.005.

Проанализируем ситуацию: если мы вычтем 0.005 из 7 167,127, мы получим 7 167,122. При обычном математическом округлении до двух знаков это число превратится в 7 167,12. Если же на входе будет 7 167,124, после вычитания получится 7 167,119, что округлится до 7 167,12 (здесь нужно быть осторожным с логикой отсечения).

Рассмотрим пример реализации:


ИсходноеЧисло = 7167.127;
Результат = Окр(ИсходноеЧисло - 0.005, 2, РежимОкругления.Окр15как20);
// Результат: 7167.12

Этот метод часто называют «хаком», и он требует обязательного комментирования в коде.

Почему стандартные режимы Окр() не помогают?

В системе 1С функция Окр() имеет третий параметр — РежимОкругления. Существует два системных режима:

Выясним причину, по которой это не решает задачу автора. Параметр РежимОкругления влияет только на ситуацию, когда следующая цифра после округляемого разряда — ровно 5. Если же там стоит 7 (как в примере 7.127), то при любом режиме система округлит число вверх до 7.13. Именно поэтому прямое использование Окр() без математических манипуляций здесь бесполезно.

Проблема точности (Floating Point)

При использовании метода Цел(Число * 100) / 100 мы можем столкнуться с неприятной особенностью представления чисел в памяти компьютера. Хотя в 1С тип Число достаточно точный, при сложных вычислениях может возникнуть эффект «плавающей точки».

Представим, что в результате каких-то расчетов число 1.13 в памяти выглядит как 1.129999999999. При умножении на 100 мы получим 112.9999999999. Функция Цел() отбросит дробь и вернет 112. После деления получится 1.12 вместо ожидаемого 1.13. Чтобы избежать таких ошибок, профессиональные разработчики иногда добавляют «микро-смещение»:


Точность = 100;
МикроСмещение = 0.000000001;
Результат = Цел(МоеЧисло * Точность + МикроСмещение) / Точность;

Округление вниз в запросах 1С

В языке запросов 1С функционал ограничен: там нет функции Цел(). Если вам нужно отбросить знаки прямо в запросе, придется использовать конструкцию ВЫРАЗИТЬ(Число КАК ЧИСЛО(15, 0)). Однако ВЫРАЗИТЬ работает по правилам математического округления.

Чтобы имитировать «отбрасывание» дробной части в запросе, мы можем использовать операцию получения остатка от деления %, а Быстрый анализ данных поможет оперативно проверить корректность работы формул:


ВЫБРАТЬ
    Продажи.Сумма - (Продажи.Сумма % 1) КАК ЦелаяЧасть
ИЗ
    РегистрНакопления.Продажи КАК Продажи

Подобные конструкции удобно тестировать, используя расширение Управляемая консоль запросов, отчетов.

Для получения двух знаков логика усложняется: нужно умножить поле на 100, вычесть остаток от деления на 1 и разделить результат на 100.

Резюме и рекомендации

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

  1. Для простого отсечения разрядов в коде используйте Цел(Число * 100) / 100. Это самый читаемый и понятный вариант.
  2. Если вы работаете с финансовыми данными, где возможны отрицательные суммы, обязательно определитесь: нужно ли вам округление к нулю или строго вниз по числовой оси.
  3. Помните, что визуальное отображение числа через функцию Формат() не меняет само число. Если вы напишете Формат(7.127, "ЧДЦ=2"), пользователь увидит 7.13, хотя в переменной останется 7.127. Подготавливайте данные до их вывода в отчет или записи в базу.
  4. При записи в реквизиты конфигурации (например, в документ или регистр), платформа сама округлит число до той точности, которая указана в настройках этого реквизита в конфигураторе. Если там стоит точность «2», то «лишний» третий знак будет округлен математически автоматически.

Надеемся, эти примеры помогут вам избежать ошибок при работе с дробными числами в 1С!

← На главную