Разработка и Конфигурация · 11 мин
Как округлить число в меньшую сторону в 1С
Как округлить число в меньшую сторону в 1С: функции Цел(), Окр(), ВЫРАЗИТЬ в запросе, округление до копеек и целых упаковок. Примеры кода и типичные ошибки.
Во встроенном языке 1С нет отдельной функции «округлить вниз» вроде Floor из других языков, поэтому задача решается комбинацией штатных средств: Цел(), Окр() с указанием режима округления, приведением типа в запросе или настройкой форматирования при выводе. Выбор способа зависит от того, где выполняется округление — в коде модуля, в запросе, в формуле печатной формы или в пользовательских настройках отчёта.
Важно понимать разницу между тремя операциями, которые часто путают: округление до ближайшего целого (математическое), отсечение дробной части (усечение) и округление в меньшую сторону (floor). Для положительных чисел усечение и округление вниз совпадают, а для отрицательных — нет: усечение −2,7 даст −2, а округление в меньшую сторону должно дать −3. В учётных задачах 1С (количество упаковок, целые штуки при списании, расчёт скидок) чаще всего нужен именно floor, и смешение этих понятий приводит к копеечным расхождениям в проводках.
Ниже разобраны все рабочие способы с примерами кода, особенностями для отрицательных чисел, округлением до нужного знака после запятой, поведением в запросах и типичными ошибками, из-за которых суммы в документах «не сходятся».
Функция Цел() — базовый способ отсечь дробную часть
Функция Цел(Число) возвращает целую часть числа, просто отбрасывая всё после запятой. Для положительных значений это и есть округление в меньшую сторону: Цел(17.95) вернёт 17, Цел(0.999) вернёт 0.
Типичный пример из торгового учёта — расчёт целого количества упаковок, которое можно отгрузить со склада:
ОстатокШтук = 100;
ШтукВУпаковке = 12;
ЦелыхУпаковок = Цел(ОстатокШтук / ШтукВУпаковке); // 8, а не 8.33
Подводный камень — отрицательные числа. Цел(-2.7) вернёт −2, потому что функция отсекает дробную часть по направлению к нулю, а не в меньшую сторону. Если в вашем алгоритме возможны отрицательные значения (сторно, корректировки, возвраты), это различие нужно учитывать обязательно.
Универсальный floor для положительных и отрицательных чисел
Если нужен строгий математический floor (всегда в меньшую сторону, независимо от знака), используйте небольшую формулу:
Функция ОкруглитьВниз(Число)
ЦелаяЧасть = Цел(Число);
Если Число < 0 И Число <> ЦелаяЧасть Тогда
Возврат ЦелаяЧасть - 1;
Иначе
Возврат ЦелаяЧасть;
КонецЕсли;
КонецФункции
Проверка: ОкруглитьВниз(2.7) → 2, ОкруглитьВниз(-2.7) → −3, ОкруглитьВниз(-2) → −2. Условие Число <> ЦелаяЧасть защищает от лишнего вычитания единицы, когда число уже целое.
Такую функцию удобно поместить в общий модуль, чтобы не дублировать логику в десятках мест. Если в конфигурации уже есть общий модуль для работы с числами или математических утилит — добавьте её туда, это стандартная практика.
Округление вниз до нужного знака: копейки, десятые, десятки
Часто округлить нужно не до целого, а до определённой разрядности: до копеек в меньшую сторону, до десятых, до целых десятков или сотен. Универсальный приём — умножить, отсечь, разделить:
// Вниз до копеек (двух знаков)
Результат = Цел(Сумма * 100) / 100;
// Вниз до десятых
Результат = Цел(Число * 10) / 10;
// Вниз до целых десятков
Результат = Цел(Число / 10) * 10;
Пример из практики: расчёт скидки, которую нельзя округлять в пользу покупателя. Цел(СуммаСкидки * 100) / 100 гарантирует, что копейка не «уедет» вверх, и сумма документа не превысит расчётную.
Учтите ограничение точности: при умножении больших чисел на 100 промежуточный результат может выйти за разумную разрядность типа Число, если она задана слишком малой в метаданных. Для денежных сумм обычно достаточно Число(15,2), но промежуточные вычисления в коде выполняются с полной точностью платформы, поэтому проблема возникает редко — в основном при записи результата в реквизит с жёсткой разрядностью.
// Округление вниз до произвольной точности
Функция ОкруглитьВнизДоТочности(Число, Точность)
Множитель = Pow(10, Точность);
Возврат Цел(Число * Множитель) / Множитель;
КонецФункции
// ОкруглитьВнизДоТочности(123.456, 2) -> 123.45Функция Окр() и режимы округления
Штатная функция Окр(Число, Разрядность, РежимОкругления) по умолчанию округляет до ближайшего значения, причём 0,5 уходит вверх (в типовых конфигурациях применяется режим «0.5 как 1»). Это не округление вниз, и использовать Окр() без понимания режима — распространённая причина расхождений.
Третий параметр принимает значения системного перечисления РежимОкругления: Округление15как10 и Округление15как20. Первый округляет 0,5 вниз, второй — вверх. Однако ни один из них не даёт настоящий floor: Окр(2.7, 0) вернёт 3 в любом режиме, потому что 0,7 ближе к единице.
Поэтому правило простое: если требование — «всегда в меньшую сторону», Окр() не подходит, используйте Цел() или формулу с множителем. Окр() уместен, когда бизнес-правило звучит как «округлить до ближайшего», а «в меньшую сторону» касается только пограничного случая 0,5.
Сравнение способов
Отсечение дробной части к нулю. Подходит для положительных чисел, для отрицательных даёт не floor.
Настоящий floor для любых чисел. Требует небольшой функции-обёртки.
Округление вниз до N знаков. Универсально для копеек и десятых.
Округление до ближайшего с управлением половинкой. Не является округлением вниз.
Округление вниз в запросах
В языке запросов 1С функции «округлить вниз» тоже нет, но есть приведение типа: ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 0)). При приведении к числу с нулевой разрядностью дробная часть отсекается — для положительных значений это округление вниз.
ВЫБРАТЬ
ВЫРАЗИТЬ(Товары.Количество / 12 КАК ЧИСЛО(15, 0)) КАК ЦелыхУпаковок
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
Тот же приём работает и для копеек: ВЫРАЗИТЬ(Сумма * 100 КАК ЧИСЛО(15, 0)) / 100. Имейте в виду, что поведение приведения типов в запросах может незначительно отличаться в зависимости от СУБД (файловая база, MS SQL, PostgreSQL), поэтому критичные к точности расчёты стоит проверить на реальных данных вашей базы.
Если результат запроса дальше обрабатывается в коде, иногда надёжнее выбрать значение как есть и округлить уже в модуле — так логика округления собрана в одном месте и проще тестируется.
- 1Определите, где выполняется округление: код модуля, запрос или вывод на форму.
- 2Проверьте, возможны ли отрицательные значения — если да, используйте floor с поправкой на знак.
- 3Определите требуемую разрядность: целые, копейки, десятки.
- 4Реализуйте округление через Цел() с множителем или ВЫРАЗИТЬ в запросе.
- 5Протестируйте на граничных значениях: 0.999, -2.7, ровно целое число.
Округление при выводе: форматная строка и Формат()
Если задача — только показать число без дробной части (в печатной форме, на форме, в отчёте), а хранить нужно точное значение, используйте функцию Формат() с конструкцией ЧДЦ:
СтрокаДляПечати = Формат(Сумма, "ЧДЦ=0"); // отображение без копеек
Важный нюанс: форматирование при выводе округляет до ближайшего, а не в меньшую сторону. Формат(2.7, "ЧДЦ=0") покажет «3». Поэтому если требуется именно отсечение, сначала примените Цел() к значению, а потом форматируйте.
То же относится к свойству «Формат» у полей формы и колонок табличных документов: оно управляет только отображением и не меняет данные в базе. Расчёты, проводки и итоги продолжат использовать исходное точное значение.
Типичные ошибки и как их проверить
Самая частая ошибка — использовать Окр(Число, 0) там, где нужен floor. На значениях вроде 2,3 результат совпадёт случайно, а на 2,7 расчёт «поплывёт» на единицу. Вторая ошибка — забыть про отрицательные числа в корректировках и возвратах: Цел(-2.7) даёт −2 вместо −3.
Третья группа ошибок — копеечные расхождения при сравнении сумм: одна часть алгоритма округляет вниз, другая до ближайшего, и итог документа не сходится с суммой строк на копейку. Лечится единым правилом округления, зафиксированным в общем модуле и применяемым везде.
Как проверить результат
Результат 17
Результат 18 — использовано округление до ближайшего вместо отсечения
Результат -3
Результат -2 — применено усечение к нулю без поправки на знак
100.99
101.00 — сработало обычное округление
Совпадает до копейки
Расхождение на копейки — в расчёте смешаны разные правила округления
FAQ: частые вопросы об округлении в меньшую сторону в 1С
Чем Цел() отличается от Окр(Число, 0)?
Цел() просто отбрасывает дробную часть в сторону нуля, а Окр() округляет до ближайшего целого. Для 2.3 обе функции дадут 2, но для 2.7 Цел() вернёт 2, а Окр() — 3. Если бизнес-правило требует «всегда вниз», применяйте Цел().
Как округлить в меньшую сторону отрицательное число?
Цел() для отрицательных чисел отсекает дробь к нулю, поэтому Цел(-2.7) даст −2. Для настоящего округления вниз добавьте поправку: если число отрицательное и не целое, вычтите единицу из целой части. Формула приведена в разделе про универсальный floor.
Как округлить сумму до копеек в меньшую сторону?
Умножьте сумму на 100, возьмите Цел() и разделите обратно на 100: Цел(Сумма * 100) / 100. Так 100.999 превратится в 100.99, а не в 101.00. Для отрицательных сумм добавьте поправку на знак по той же схеме.
Можно ли округлить вниз прямо в запросе 1С?
Да, через приведение типа: ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 0)) отсекает дробную часть. Для копеек — ВЫРАЗИТЬ(Сумма * 100 КАК ЧИСЛО(15, 0)) / 100. Проверьте поведение на своей СУБД, если расчёт критичен к точности.
Почему печатная форма показывает одно, а итоги — другое?
Форматная строка (ЧДЦ=0 и подобные) меняет только отображение и округляет до ближайшего, а данные в документе остаются с полной точностью. Чтобы форма и итоги совпадали, округляйте само значение через Цел() до записи или вывода, а не только форматирование.
Есть ли готовая функция округления вниз в типовых конфигурациях?
Отдельной функции floor в стандартных подсистемах нет — в типовых решениях используются Цел(), Окр() и вспомогательные процедуры общих модулей. Практичное решение — добавить собственную функцию ОкруглитьВниз() в общий модуль и вызывать её во всех расчётах, где нужен единый принцип округления.
Что важно запомнить
Округление в меньшую сторону в 1С делается через Цел() для положительных чисел, через Цел() с поправкой на знак — для любых, через Цел(Число * 10^N) / 10^N — для нужной разрядности, а в запросах — через ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 0)). Функция Окр() округляет до ближайшего и для floor не подходит. Единое правило округления во всех расчётах защищает от копеечных расхождений.