Целая часть числа во встроенном языке и запросах 1С 8.3

· 9 мин

Содержание

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

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

Функция Цел(): как получить целую часть числа

Цел() — встроенная функция платформы 1С:Предприятие 8.3. Она работает одинаково в любой конфигурации: БП 3.0, ЗУП 3.1, УТ 11, ERP или своей разработке. Доступна на клиенте и на сервере, директивы компиляции не нужны.

Что делает функция:

  • ✂️ отбрасывает всё, что стоит после запятой;
  • ➡️ двигается к нулю, а не вниз по числовой оси;
  • 🔢 возвращает значение типа Число, а не строку;
  • 🚫 ничего не округляет: Цел(9.9999) даст 9.

Последний пункт — главная причина, по которой функцию выбирают. Округление «по-бухгалтерски» тут не нужно: если в коробку входит 12 штук, а на складе 35, полных коробок 2, а не 3.

ВыражениеРезультат
Цел(5.2)5
Цел(5.8)5
Цел(5)5
Цел(0.99)0
Цел(-5.2)-5
Цел(-5.8)-5

Синтаксис Цел() и примеры кода

Синтаксис короткий: один параметр, тип Число.

Результат = Цел(Число);

Простой пример в процедуре:

Количество = 35;
ВКоробке = 12;

ПолныхКоробок = Цел(Количество / ВКоробке);      // 2
Остаток = Количество - ПолныхКоробок * ВКоробке; // 11

Сообщить("Коробок: " + Формат(ПолныхКоробок, "ЧГ=0")
	+ ", штук россыпью: " + Формат(Остаток, "ЧГ=0"));

Проверим арифметику: 35 / 12 = 2,916…; целая часть 2; 2 × 12 = 24; 35 − 24 = 11.

Дробная часть числа

Дробную часть получают вычитанием:

Число = 128.47;
ЦелаяЧасть  = Цел(Число);           // 128
ДробнаяЧасть = Число - Цел(Число);  // 0.47

Для отрицательного числа дробная часть тоже будет отрицательной: -3.25 - Цел(-3.25) = -3.25 - (-3) = -0.25.

Проверка, что число целое

Частая задача — убедиться, что пользователь ввёл целое количество, а не 2,5 штуки.

Функция ЭтоЦелоеЧисло(Значение) Экспорт
	
	Если ТипЗнч(Значение) <> Тип("Число") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Значение = Цел(Значение);
	
КонецФункции

Сравнение Значение = Цел(Значение) надёжно: числа в 1С десятичные, поэтому 0.1 + 0.2 в 1С даёт ровно 0.3, без «хвостов», привычных по другим языкам.

Чем Цел() отличается от Окр() и округления вниз

Путают эти функции постоянно. Разница в том, что делать с дробью.

ЧислоЦел()Окр(Ч, 0)Вниз (floor)Вверх (ceil)
7.37778
7.57878
7.87878
-7.3-7-7-8-7
-7.8-7-8-8-7

Для положительных чисел Цел() совпадает с округлением вниз. Для отрицательных — нет: Цел(-7.3) = -7, а математическое округление вниз даёт -8.

Как работает Окр()

Полный синтаксис: Окр(Число, Разрядность, РежимОкругления).

  • 🎯 Разрядность — сколько знаков оставить после запятой. Ноль — до целого.
  • ↩️ Отрицательная разрядность округляет до десятков, сотен: Окр(1234.5, -2) = 1200.
  • ⚖️ РежимОкругления.Окр15как20 — пятёрка округляется вверх по модулю: Окр(2.5, 0) = 3. Это режим по умолчанию.
  • ⚖️ РежимОкругления.Окр15как10 — пятёрка отбрасывается: Окр(2.5, 0, РежимОкругления.Окр15как10) = 2.
А = Окр(2.5, 0);                                // 3
Б = Окр(2.5, 0, РежимОкругления.Окр15как10);    // 2
В = Окр(2.4999, 0, РежимОкругления.Окр15как20); // 2
Г = Окр(1234.5, -2);                            // 1200

Окр(Ч, 0, РежимОкругления.Окр15как10) — не аналог Цел(). Число 7.8 так округлится до 8. Режим влияет только на ровную пятёрку.

Формат() тоже округляет

Формат(7.8, "ЧДЦ=0") вернёт строку 8, а не 7. Форматная строка округляет число для показа. Если на печатной форме нужна именно целая часть, сначала Цел(), потом Формат():

Строка = Формат(Цел(7.8), "ЧДЦ=0; ЧГ=0"); // "7"

Целая часть в языке запросов 1С

В запросе вызвать Цел() из встроенного языка нельзя. Есть три пути.

Способ 1. ВЫРАЗИТЬ с поправкой

ВЫРАЗИТЬ(Х КАК ЧИСЛО(15, 0)) приводит число к типу без знаков после запятой. При этом СУБД округляет значение: 7,8 станет 8. Чтобы получить округление вниз, сравниваем результат с исходным числом:

ВЫБРАТЬ
	Товары.Номенклатура КАК Номенклатура,
	Товары.Количество КАК Количество,
	ВЫБОР
		КОГДА ВЫРАЗИТЬ(Товары.Количество / 12 КАК ЧИСЛО(15, 0)) > Товары.Количество / 12
			ТОГДА ВЫРАЗИТЬ(Товары.Количество / 12 КАК ЧИСЛО(15, 0)) - 1
		ИНАЧЕ ВЫРАЗИТЬ(Товары.Количество / 12 КАК ЧИСЛО(15, 0))
	КОНЕЦ КАК ПолныхКоробок
ИЗ
	Документ.РеализацияТоваровУслуг.Товары КАК Товары

Логика простая: если после приведения число стало больше исходного, значит, его округлило вверх — вычитаем единицу. Приём не зависит от того, как конкретная СУБД обрабатывает ровную пятёрку, поэтому одинаково работает в файловой базе, на MS SQL и PostgreSQL.

Для отрицательных значений этот код даёт округление вниз (−7,3 → −8). Если нужно поведение как у Цел() (к нулю), добавьте ветку: для отрицательных чисел вычитать единицу не надо, а прибавлять, когда результат приведения оказался меньше исходного.

Деление на поле в запросе защищайте: ВЫБОР КОГДА Т.ВКоробке = 0 ТОГДА 0 ИНАЧЕ … КОНЕЦ. Деление на ноль в запросе прерывает его выполнение.

Способ 2. Функция ЦЕЛ в запросе (новые версии платформы)

Начиная с платформы 8.3.20 в язык запросов добавлены математические функции, среди них ЦЕЛ() и ОКР(). Они работают, если режим совместимости конфигурации не ниже 8.3.20. В типовых конфигурациях режим совместимости часто стоит ниже, поэтому проверьте его в свойствах конфигурации, прежде чем писать такой код. Если режим ниже — используйте способ 1.

Способ 3. Посчитать после запроса

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

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	ПолныхКоробок = Цел(Выборка.Количество / 12);
	// ...
КонецЦикла;

Для отчёта на СКД есть вариант без кода в модуле: вычисляемое поле, в выражении которого вызывается экспортная функция общего модуля с Цел() внутри. Общий модуль должен быть доступен на сервере.

Альтернативные способы и математические приёмы

Когда Цел() сам по себе не подходит, его дополняют. Ниже — готовые функции для общего модуля.

Округление вниз (floor) для любого знака

Функция ОкруглитьВниз(Число) Экспорт
	ЦелаяЧасть = Цел(Число);
	Если Число < ЦелаяЧасть Тогда
		Возврат ЦелаяЧасть - 1;
	КонецЕсли;
	Возврат ЦелаяЧасть;
КонецФункции

Проверка: для -7.3 целая часть -7; -7.3 < -7 — истина; результат -8. Для 7.3 условие ложно, ответ 7.

Округление вверх (ceil)

Функция ОкруглитьВверх(Число) Экспорт
	ЦелаяЧасть = Цел(Число);
	Если Число > ЦелаяЧасть Тогда
		Возврат ЦелаяЧасть + 1;
	КонецЕсли;
	Возврат ЦелаяЧасть;
КонецФункции

Проверка: 7.3 → 8; -7.3 → целая часть -7, условие -7.3 > -7 ложно, ответ -7. Ровное число 7 не меняется.

Остаток от деления: оператор %

Во встроенном языке 1С есть оператор остатка %. Вместе с Цел() он закрывает целочисленное деление:

Частное = Цел(35 / 12); // 2
Остаток = 35 % 12;      // 11

Для чётности: Число % 2 = 0. Для «каждой третьей строки»: НомерСтроки % 3 = 0.

Округление до кратного

Цены до 10 рублей вниз, количество до кратности упаковки:

ЦенаВниз = Цел(Цена / 10) * 10;          // 1287 → 1280
Кратно6  = Цел(Количество / 6) * 6;      // 40 → 36

Ошибки при получении целой части и как их исправить

Диагностика: выберите симптом

Ещё две ловушки, о которых не скажет сообщение об ошибке:

  1. Строка с запятой. Число("3,7") и Число("3.7") в разных региональных настройках ведут себя по-разному. Если значение пришло из файла или внешней системы, замените разделитель через СтрЗаменить() до преобразования.
  2. Неопределено в реквизите. У пустого составного реквизита значение Неопределено, и Цел() на нём упадёт. Проверка: Если ЗначениеЗаполнено(Значение) И ТипЗнч(Значение) = Тип("Число").

Практические задачи: где нужна целая часть числа

Несколько сценариев, которые встречаются в доработках учётных конфигураций.

Рубли и копейки

Сумма = 15420.37;
Рубли   = Цел(Сумма);                 // 15420
Копейки = Окр((Сумма - Рубли) * 100); // 37

Копейки округляем через Окр(), чтобы не потерять одну копейку на суммах, которые пришли с лишними знаками после расчётов.

Количество страниц или пачек

Нужно разбить 103 строки по 25 на страницу. Полных страниц Цел(103 / 25) = 4, но всего страниц 5. Здесь нужна функция ОкруглитьВверх(103 / 25): 4,12 → 5.

Полные годы и месяцы между датами

Разность дат в 1С — число секунд. Полные дни:

ДнейМежду = Цел((ДатаОкончания - ДатаНачала) / 86400);

86 400 — секунд в сутках. Для полных лет точнее не делить на 365, а сравнивать даты через ДобавитьМесяц(ДатаНачала, 12 * Лет): високосные годы иначе дадут сбой на границе.

Разбивка суммы на равные части

Разделить 1 000 рублей на 3 платежа:

Всего = 1000;
Частей = 3;
Платёж = Цел(Всего / Частей * 100) / 100; // 333.33
Последний = Всего - Платёж * (Частей - 1); // 333.34

Проверка: 333,33 × 2 = 666,66; 1000 − 666,66 = 333,34. Сумма платежей сходится до копейки — остаток уходит в последний платёж.

Номер квартала по дате

Квартал удобно получить из номера месяца целочисленным делением:

Квартал = Цел((Месяц(Дата) - 1) / 3) + 1;

Проверка: январь — Цел(0 / 3) + 1 = 1; март — Цел(2 / 3) + 1 = 1; апрель — Цел(3 / 3) + 1 = 2; декабрь — Цел(11 / 3) + 1 = 4. Для самих границ квартала в платформе есть НачалоКвартала() и КонецКвартала(), а номер нужен для группировок и подписей в отчётах.

Проверьте себя
Что вернёт Цел(-4.9)?
Чему равно Окр(3.5, 0, РежимОкругления.Окр15как10)?
Что вернёт 17 % 5?

Частые вопросы

Есть ли в 1С функции Floor и Ceiling?
Нет, отдельных функций округления вниз и вверх во встроенном языке нет. Их пишут на основе Цел() в общем модуле — по две-три строки кода.
Можно ли вызвать Цел() на клиенте?
Да. Цел(), Окр() и оператор % доступны и на клиенте, и на сервере, в том числе в веб-клиенте.
Как взять целую часть числа в формуле макета или вычисляемом поле СКД?
В выражении вычисляемого поля вызовите экспортную функцию общего модуля, внутри которой стоит Цел(). Модуль должен компилироваться на сервере.
Цел() меняет исходную переменную?
Нет. Функция возвращает новое значение, исходная переменная остаётся прежней. Чтобы заменить, присвойте результат: Ч = Цел(Ч).
Как получить целую часть от строки «12,75»?
Сначала переведите строку в число через Число(), при необходимости заменив разделитель через СтрЗаменить(), затем примените Цел(). Вызов оберните в Попытка … Исключение.