В процессе разработки на платформе 1С программисты часто сталкиваются с необходимостью округления вычисляемых значений непосредственно в тексте запроса. Типичная ситуация: при расчете остатков с учетом коэффициентов упаковок или при пересчете валют необходимо округлить результат до определенного количества знаков. Трудность возникает тогда, когда это количество знаков не является фиксированным, а хранится в справочнике (например, в поле Номенклатура.ЕдиницаХраненияОстатков.КоэффициентОкругления) или передается как параметр.
Разберем детально, почему стандартные методы могут не работать и какие существуют проверенные способы решения этой задачи для разных версий платформы 1С:Предприятие.
Проанализируем попытку использования классической функции ВЫРАЗИТЬ. Многие начинающие разработчики пытаются написать код следующим образом:
ВЫРАЗИТЬ(Количество * Коэффициент / Номенклатура.ЕдиницаХраненияОстатков.Коэффициент
КАК ЧИСЛО(10, Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления))
При попытке сохранить такой запрос система выдаст ошибку. Выясним причину: согласно синтаксису языка запросов 1С, второй параметр функции ВЫРАЗИТЬ (точность) обязательно должен быть константой (литералом). Платформа должна знать структуру результирующей таблицы еще до момента выполнения запроса, поэтому подстановка поля базы данных или параметра в описание типа ЧИСЛО(Длина, Точность) недопустима.
Рассмотрим самый современный способ. Начиная с версии платформы 8.3.20, в языке запросов появилась полноценная функция ОКР(). Это значительно упростило жизнь разработчикам, так как ранее округление приходилось имитировать сложными математическими выкладками.
Синтаксис функции выглядит так:
ОКР(Число, Разрядность)
Однако здесь есть важный нюанс, который мы должны учитывать: параметр Разрядность все равно должен быть целым числом-константой. Если ваша задача — округлить до заранее известного количества знаков, этот метод идеален:
ВЫБРАТЬ
ОКР(Продажи.Сумма / Продажи.Курс, 2) КАК СуммаВВалюте
ИЗ
РегистрНакопления.Продажи КАК Продажи
Важные особенности ОКР() в запросе:
Если количество знаков после запятой может меняться в зависимости от условий (например, для одного товара это 0 знаков, для другого — 3), и мы работаем в рамках одного запроса, наиболее надежным методом будет использование оператора ВЫБОР. Проанализируем пример реализации:
ВЫБРАТЬ
ВЫБОР
КОГДА Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления = 0
ТОГДА ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 0))
КОГДА Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления = 1
ТОГДА ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 1))
КОГДА Номенклатура.ЕдиницаХраненияОстатков.лКоэффициентОкругления = 2
ТОГДА ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 2))
ИНАЧЕ ВЫРАЗИТЬ(Таблица.Значение КАК ЧИСЛО(15, 3))
КОНЕЦ КАК РезультатОкругления
ИЗ
ВременнаяТаблица КАК Таблица
Этот метод кажется громоздким, но он обладает максимальной производительностью, так как транслируется в эффективный SQL-код, понятный любому серверу баз данных (MS SQL, PostgreSQL). Рассмотрим его преимущества: мы явно управляем типами данных и избегаем ошибок переполнения.
Бывают ситуации, когда количество знаков может быть очень большим или оно вычисляется по сложной формуле, и писать бесконечные ВЫБОР КОГДА неудобно. В таком случае мы можем применить математический алгоритм округления. Разберем его по шагам:
N (где N — нужное количество знаков).ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 0)).N.Посмотрим на пример кода в запросе, где точность передается через параметр:
ВЫБРАТЬ
// Предположим, нам нужно округлить до знаков, указанных в &КоэффициентМножитель (например, 100 для 2 знаков)
ВЫРАЗИТЬ(Таблица.Цена * &КоэффициентМножитель + 0.5 КАК ЧИСЛО(15, 0)) / &КоэффициентМножитель КАК ОкругленнаяЦена
ИЗ
Справочник.Номенклатура КАК Таблица
Внимание: Основная сложность этого метода в том, что в чистом языке запросов 1С нет функции возведения в степень (POW). Поэтому коэффициент (10, 100, 1000) нужно либо заранее подготовить в коде на встроенном языке и передать в параметр, либо хранить в базе данных.
Если ваш запрос является частью отчета на СКД, возможности округления расширяются. Проанализируем возможности компоновки:
Окр(), даже если версия платформы ниже 8.3.20.ЧДЦ=2 (Число Десятичных Цифр).Если запрос формируется программно, мы можем использовать объект СхемаЗапроса. Это позволяет динамически модифицировать текст запроса перед его выполнением. Проанализируем этот путь:
Вместо того чтобы пытаться вставить переменную в текст запроса, мы программно формируем строку ВЫРАЗИТЬ(... КАК ЧИСЛО(15, " + НужнаяТочность + ")) и подставляем её в дерево запроса. Это позволяет избежать жестко заданных конструкций ВЫБОР, сохраняя типизацию данных.
Выясним, какой метод лучше выбрать в зависимости от ситуации:
ОКР().ВЫБОР КОГДА. Это самый надежный способ с точки зрения типов данных СУБД.Используя предложенные методы, вы сможете гибко настраивать точность вычислений в ваших прикладных решениях на базе 1С, обеспечивая корректность данных и удобство для пользователей.