Как реализовать алгоритм округления в 1С 8.3 без преобразования в строку

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

При разработке прикладных решений на платформе 1С 8.3 часто возникает необходимость не просто округлить число по стандартным математическим правилам, но и реализовать специфические режимы округления. Например, округлить число всегда в большую сторону (вверх) или отсечь лишние знаки после запятой без изменения самого числа (вниз). Начинающие разработчики часто решают эту задачу через преобразование числа в строку, поиск запятой и манипуляции с подстроками. Проанализируем, почему этот метод неэффективен, и разберем по шагам, как построить красивый, быстрый и точный математический алгоритм.

Почему преобразование числа в строку для округления — это плохая практика?

Рассмотрим типичный подход начинающего разработчика. Число преобразуется в строку с помощью функции Строка(), затем через Найти() определяется позиция разделителя (запятой или точки), после чего строковыми функциями Лев() и Сред() выделяются нужные фрагменты для последующего анализа и сборки нового числа.

Этот метод рабочий, но имеет несколько критических недостатков:

  1. Зависимость от региональных настроек. В зависимости от настроек операционной системы разделителем дробной части может выступать как запятая, так и точка. Строковый алгоритм, завязанный на поиск конкретного символа (например, только запятой), гарантированно даст сбой на сервере с другими региональными стандартами.
  2. Низкая производительность. Преобразование типов «число-строка-число» требует выделения дополнительной памяти и нагружает процессор. В циклах обработки тысяч документов или строк табличных частей это приведет к заметному замедлению работы системы.
  3. Сложность поддержки кода. Код с обилием строковых функций трудно читать и легко сломать при внесении изменений.

Проанализируем ситуацию и выясним, как решить задачу исключительно математическими методами встроенного языка 1С.

Разбор математического подхода: избавляемся от строк

Для реализации корректного округления без строк нам понадобятся базовые арифметические операции и несколько встроенных функций 1С:

Давайте разберем принцип работы математического сдвига разрядов. Чтобы оставить у числа 250.35941 ровно 2 знака после запятой, выполним следующие шаги:

  1. Вычислим коэффициент сдвига. Для 2 знаков после запятой коэффициент равен 10 во второй степени: 10 * 10 = 100.
  2. Умножим исходное число на полученный коэффициент: 250.35941 * 100 = 25035.941. Теперь целевые разряды округления оказались в целой части числа.
  3. Применим операции отсечения или округления к полученному значению.
  4. Разделим результат обратно на коэффициент 100, чтобы вернуть запятую на место: 25035 / 100 = 250.35.

Рассмотрим, как этот алгоритм выглядит на практике для разных режимов округления.

Реализация трех режимов округления: «Вверх», «Вниз», «Математическое»

Нам необходимо реализовать функцию, принимающую три параметра: округляемое число, количество знаков после запятой (разрядность) и режим («Вверх», «Вниз» или «Нет» — стандартное математическое округление).

Посмотрим на пример законченной и оптимизированной функции:


Функция ОкруглитьЧислоМатематически(Знач ИсходноеЧисло, Знач Разрядность, Знач РежимОкругления) Экспорт
    
    // Если разрядность некорректная, возвращаем исходное число
    Если Разрядность < 0 Тогда
        Возврат ИсходноеЧисло;
    КонецЕсли;
    
    // Вычисляем коэффициент сдвига запятой (10, 100, 1000 и т.д.)
    Коэффициент = Pow(10, Разрядность);
    
    // Сдвигаем запятую вправо
    СдвинутоеЧисло = ИсходноеЧисло * Коэффициент;
    
    Если РежимОкругления = "Вниз" Тогда
        // Режим "Вниз" (простое усечение/отсечение дробной части)
        Возврат Цел(СдвинутоеЧисло) / Коэффициент;
        
    ИначеЕсли РежимОкругления = "Вверх" Тогда
        // Режим "Вверх" (округление всегда в большую сторону, если есть остаток)
        Если Дробь(СдвинутоеЧисло) > 0 Тогда
            Возврат (Цел(СдвинутоеЧисло) + 1) / Коэффициент;
        Иначе
            Возврат СдвинутоеЧисло / Коэффициент;
        КонецЕсли;
        
    Иначе // Режим "Нет" (по правилам математики)
        // Используем быструю встроенную функцию платформы
        Возврат Окр(ИсходноеЧисло, Разрядность);
    КонецЕсли;
    
КонецФункции

Как работает данный алгоритм?

Рассмотрим подробнее каждый режим работы функции:

  1. Режим «Вниз». Мы умножаем число 250.35941 на 100, получая 25035.941. Функция Цел() отбрасывает дробную часть 0.941, оставляя ровно 25035. При делении на 100 мы получаем итоговое значение 250.35. Метод работает мгновенно и без строковых преобразований.
  2. Режим «Вверх». Мы анализируем дробную часть сдвинутого числа с помощью функции Дробь(). Если у числа 25035.941 дробная часть (0.941) больше нуля, это значит, что число не было целым и его нужно округлить в большую сторону. Мы берем целую часть 25035, прибавляем к ней 1 (получаем 25036) и делим на 100. Результат — 250.36.
  3. Режим «Нет» (Математическое округление). Для стандартного математического округления нет необходимости изобретать велосипед. Встроенная функция 1С Окр() отлично справляется с этой задачей, работая на уровне скомпилированного кода платформы с максимальной скоростью.

Важные особенности стандартной функции Окр()

Разработчикам полезно знать возможности стандартной функции Окр(), которые могут избавить от написания собственного кода:

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

Начиная с версии платформы 8.3.20, разработчикам больше не нужно использовать сложные конструкции вроде ВЫРАЗИТЬ() или выгружать данные в код для округления. В язык запросов и СКД были добавлены полноценные математические функции:

Использование этих функций в запросах позволяет значительно повысить производительность отчетов и обработок, перекладывая математические вычисления на СУБД.

← На главную