Как правильно округлить число до двух знаков в запросе 1С?

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

При работе с отчетами и сложными расчетами в 1С программисты часто сталкиваются с ситуацией, когда стандартные методы округления в запросах выдают «странные» результаты. Казалось бы, функция ВЫРАЗИТЬ должна работать предсказуемо, но на практике возникают расхождения в копейках, которые вызывают массу вопросов у пользователей и бухгалтеров. В этой статье мы подробно разберем, почему возникают такие ошибки и как добиться нужного результата округления в различных ситуациях.

Причина проблемы: Математическое округление и точность

Прежде всего, проанализируем, как работает функция ВЫРАЗИТЬ(Число КАК ЧИСЛО(15,2)). В языке запросов 1С эта конструкция транслируется в SQL-команду CAST. Большинство современных СУБД (MS SQL Server, PostgreSQL) используют стандартное математическое округление. Если третья цифра после запятой меньше 5, число округляется вниз, если 5 и больше — вверх.

Однако при выполнении деления в запросе, например, База * Результат / Сумма, результат может получиться с очень длинной дробной частью (например, 3140,943999...). Даже если визуально нам кажется, что число должно округлиться определенным образом, микроскопические погрешности в 15-м знаке после запятой, возникающие из-за специфики вычислений с плавающей точкой, могут изменить результат округления.

Различие между округлением слагаемых и округлением итога

Рассмотрим самую частую ошибку, с которой столкнулся автор темы. Проблема заключалась в использовании агрегатной функции СУММА вместе с округлением. Существует два принципиально разных подхода, которые дают разные результаты:

  1. Сумма округленных значений: Вы округляете каждую строку в отдельности, а затем складываете их. Это гарантирует, что если пользователь сложит строки отчета на калькуляторе, итоговая сумма совпадет. Однако общая точность расчета может пострадать.
  2. Округление итоговой суммы: Вы сначала складываете все точные (неокругленные) значения, а затем один раз округляете результат. Это математически точнее, но может привести к «раздору в копейку», когда сумма видимых строк отчета не совпадает с итогом.

Проанализируем пример кода, который помог автору решить проблему. Ошибка была в том, что округление происходило внутри функции ВЫБОР для каждой строки:


// Неправильно: округление каждой строки перед суммированием
СУММА(ВЫБОР 
    КОГДА ЕстьNULL(ВТСумма.Результат, 0) = 0 ТОГДА 0 
    ИНАЧЕ ВЫРАЗИТЬ(База * Коэффициент / Знаменатель КАК ЧИСЛО(15, 2)) 
КОНЕЦ)

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


// Правильно: сначала суммируем точные данные, затем округляем итог
ВЫРАЗИТЬ(СУММА(ВЫБОР 
    КОГДА ЕстьNULL(ВТСумма.Результат, 0) = 0 ТОГДА 0 
    ИНАЧЕ База * Коэффициент / Знаменатель 
КОНЕЦ) КАК ЧИСЛО(15, 2))

Метод «отсечения» (Truncate) вместо округления

Иногда требования бизнес-логики специфичны: нужно не округлять число по математическим правилам, а просто «отрезать» лишние знаки. В языке запросов 1С нет функции ЦЕЛ() для работы с дробной частью внутри запроса, но мы можем использовать математические хитрости.

Чтобы просто отсечь знаки после второго знака (сделать из 3140,946 число 3140,94), воспользуемся следующей формулой:

(ВЫРАЗИТЬ(ВашеЧисло * 100 - 0.5000000001, ЧИСЛО(15, 0))) / 100

Разберем, как это работает. Мы умножаем число на 100, перенося два знака в целую часть. Затем вычитаем небольшое смещение и округляем до целого числа (0 знаков после запятой). После деления обратно на 100 мы получаем исходное число без лишних знаков.

Двойное округление для повышения стабильности

В некоторых случаях числа находятся в пограничном состоянии (например, 1135,734999). Обычное округление до 2-х знаков превратит его в 1135,73. Но если бизнес-логика требует, чтобы такое число стало 1135,74, можно применить метод ступенчатого округления:

Сначала округлим число до 3-х знаков, а результат — до 2-х. Рассмотрим пример:

  1. Исходное число: 1135,734999
  2. Шаг 1 (до 3-х знаков): ВЫРАЗИТЬ(1135.734999 КАК ЧИСЛО(15,3)) -> получаем 1135,735
  3. Шаг 2 (до 2-х знаков): ВЫРАЗИТЬ(1135.735 КАК ЧИСЛО(15,2)) -> получаем 1135,74

Такой подход позволяет «подтянуть» значения, которые из-за погрешностей вычислений оказались чуть меньше порога округления вверх.

Практические советы по работе с точностью в запросах

Выясним причины, по которым округление может вести себя нестабильно, и как этого избежать:

Подводя итог, можно сказать, что универсального способа округления «для всех» не существует. Выбор метода зависит от того, что важнее в конкретном отчете: математическая точность итоговой суммы или визуальное соответствие слагаемых и результата. Теперь, зная особенности работы функции ВЫРАЗИТЬ и агрегата СУММА, вы сможете осознанно выбирать нужный подход в своих разработках.

← На главную