К статье
Практический материал

Разработка и Конфигурация · 10 мин

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

Как в 1С проверить, является ли число целым: Цел(), Окр(), остаток от деления, проверка типа значения. Примеры кода, ошибки и готовые функции для разработчика.

Проверка на целое число — частая задача при разработке на встроенном языке 1С. Она возникает при валидации введённых пользователем данных, при расчёте количества упаковок, штук товара, при разбиении сумм и в алгоритмах обмена данными, где дробные значения недопустимы. Встроенной функции вида «ЭтоЦелоеЧисло()» в платформе нет, поэтому проверку реализуют через стандартные математические функции.

Есть несколько рабочих подходов: сравнение числа с его целой частью через функцию Цел(), сравнение с округлённым значением через Окр(), проверка остатка от деления на единицу, а также анализ типа значения и разрядности числа через метаданные. Выбор зависит от того, что именно нужно: проверить математическую целочисленность значения или убедиться, что переменная имеет целочисленный тип по описанию.

Ниже разобраны все основные способы с готовыми фрагментами кода, указаны их ограничения и типичные ошибки, которые приводят к неверным результатам проверки.

Проверка через функцию Цел() — базовый способ

Функция Цел() возвращает целую часть числа, отбрасывая дробную без округления. Если исходное значение равно своей целой части, значит, дробной части нет и число целое. Это самый простой и читаемый вариант проверки.

Функция ЭтоЦелоеЧисло(Значение)

Возврат Значение = Цел(Значение);

КонецФункции

// Примеры использования:

// ЭтоЦелоеЧисло(10) — Истина

// ЭтоЦелоеЧисло(10.5) — Ложь

// ЭтоЦелоеЧисло(-7) — Истина

// ЭтоЦелоеЧисло(-7.3) — Ложь

Обратите внимание на поведение с отрицательными числами: Цел(-7.3) возвращает -7, то есть функция отбрасывает дробную часть в сторону нуля. Для проверки на целость это не важно — сравнение -7.3 = -7 корректно даст Ложь, а -7 = -7 даст Истина.

Способ работает с любыми числовыми значениями, включая числа с большой разрядностью. Ограничение одно: на вход должно прийти именно число. Если передать строку или Неопределено, платформа выдаст ошибку «Преобразование значения к типу Число не может быть выполнено».

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

Проверка через остаток от деления

Во встроенном языке 1С есть оператор остатка от деления — символ процента %. Если разделить число на 1 и остаток равен нулю, число целое. Логика та же, что и у Цел(), но запись короче.

Если Количество % 1 = 0 Тогда

// Число целое

Иначе

// Есть дробная часть

КонецЕсли;

Оператор % также применяют, когда нужно проверить кратность не единице, а другому числу. Например, проверка, что количество товара кратно размеру упаковки:

Если КоличествоТовара % КоличествоВУпаковке <> 0 Тогда

Сообщить("Количество должно быть кратно " + КоличествоВУпаковке);

КонецЕсли;

Проверка через округление Окр()

Функция Окр(Число, 0) округляет значение до нуля знаков после запятой. Если результат округления совпадает с исходным числом, дробной части не было. Способ эквивалентен проверке через Цел(), но иногда удобнее, когда округление уже используется в соседнем коде.

Функция ЭтоЦелоеЧисло(Значение)

Возврат Значение = Окр(Значение, 0);

КонецФункции

Разница между Цел() и Окр() проявляется только в самом результате функций, а не в проверке: Окр(2.7, 0) вернёт 3, а Цел(2.7) вернёт 2. Но для сравнения «равно исходному или нет» оба варианта дают одинаковый итог.

Проверка типа значения перед сравнением

Частая ситуация: значение приходит из реквизита формы, результата запроса или параметра, и заранее неизвестно, число это или нет. Проверка на целое без предварительного анализа типа — источник ошибок выполнения. Поэтому в универсальных функциях сначала проверяют тип.

Функция ЭтоЦелоеЧисло(Значение) Экспорт

Если ТипЗнч(Значение) <> Тип("Число") Тогда

Возврат Ложь;

КонецЕсли;

Возврат Значение = Цел(Значение);

КонецФункции

Если значение может прийти строкой (например, из файла или поля ввода), добавьте попытку преобразования. Прямое Число(Строка) вызовет исключение на нечисловых данных, поэтому используют Попытка...Исключение либо предварительный разбор строки.

Функция СтрокаЯвляетсяЦелымЧислом(Строка)

Попытка

Значение = Число(Строка);

Исключение

Возврат Ложь;

КонецПопытки;

Возврат Значение = Цел(Значение);

КонецФункции

Типичные ошибки
01
Проверять строку напрямую через Цел() — получите ошибку преобразования типа в момент выполнения
02
Сравнивать дробные числа после арифметики на точное равенство без учёта погрешности — 0.1 + 0.2 может не совпасть с 0.3 из-за двоичного представления
03
Путать проверку «число целое» с проверкой «тип Число» — значение 10.5 тоже имеет тип Число, но целым не является
04
Забывать про отрицательные значения и тестировать функцию только на положительных

Проверка разрядности реквизита через метаданные

Иногда нужно проверить не конкретное значение, а само определение реквизита: может ли он вообще хранить дробную часть. Например, в универсальной обработке, которая анализирует произвольный документ. Это делается через описание типа и квалификаторы числа.

ОписаниеТипа = РеквизитОбъекта.ТипЗначения; // или из метаданных

Квалификаторы = ОписаниеТипа.КвалификаторыЧисла;

Если Квалификаторы.РазрядностьДробнойЧасти = 0 Тогда

// Реквизит хранит только целые числа

КонецЕсли;

Тот же подход работает при обходе метаданных: у объекта Метаданные.Документы.ИмяДокумента.Реквизиты.ИмяРеквизита.Тип доступны те же квалификаторы числа. Свойство РазрядностьДробнойЧасти, равное нулю, означает целочисленный реквизит.

Сравнение способов

Значение = Цел(Значение)

Универсальный и читаемый вариант, подходит почти всегда. Требует, чтобы значение уже было числом

Значение % 1 = 0

Короткая запись, удобен при проверках кратности. Менее очевиден для читающего код

Значение = Окр(Значение, 0)

Эквивалент Цел(), удобен если округление уже применяется рядом в алгоритме

Квалификаторы числа

Проверяет определение реквизита, а не значение. Нужен в универсальных обработках и анализе метаданных

Проверка результата деления и практические сценарии

Типичный прикладной сценарий — проверить, делится ли одно число на другое без остатка. Здесь проверка на целое применяется к результату деления:

Результат = Делимое / Делитель;

Если Результат = Цел(Результат) Тогда

// Делится нацело

КонецЕсли;

Тот же код короче записывается через остаток: Если Делимое % Делитель = 0 Тогда. Второй вариант предпочтительнее, потому что не создаёт промежуточного дробного значения и исключает проблемы точности при делении больших чисел.

Ещё один сценарий — валидация количества в табличной части документа. Если по бизнес-логике количество должно быть целым (штуки, а не доли), проверку размещают в обработчике ПередЗаписью или ОбработкаПроверкиЗаполнения и отказывают в проведении при дробном значении.

Порядок действий
  1. 1
    Определите, что проверяете: значение переменной или определение реквизита
  2. 2
    Для переменной сначала убедитесь, что тип значения — Число, через ТипЗнч()
  3. 3
    Примените сравнение Значение = Цел(Значение) или Значение % 1 = 0
  4. 4
    Для строки сначала выполните преобразование Число() внутри Попытка...Исключение
  5. 5
    Протестируйте функцию на положительных, отрицательных, нулевом и дробном значениях

Ограничения и подводные камни

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

Отдельный нюанс — значение Неопределено и NULL из запросов. Перед проверкой на целое их нужно отфильтровать, иначе сравнение и вызов Цел() завершатся ошибкой. В запросах для этого используют ЕСТЬNULL(Поле, 0), а в коде — явную проверку ЗначениеЗаполнено() и ТипЗнч().

Наконец, не используйте проверку на целое как замену контролю ввода. Если реквизит по смыслу целочисленный, правильнее задать ему нулевую разрядность дробной части в конфигураторе — тогда платформа сама не даст ввести дробь, и отдельная проверка в коде станет лишь дополнительной страховкой.

Итог

Что важно запомнить

Проверка на целое в 1С сводится к сравнению значения с его целой частью: Значение = Цел(Значение) или Значение % 1 = 0. Всегда проверяйте тип значения перед сравнением, строки преобразовывайте через Попытка...Исключение, а для реквизитов, которые должны быть целыми по смыслу, задавайте нулевую разрядность дробной части в метаданных.

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

Как проверить, что строка содержит целое число?

Преобразуйте строку функцией Число() внутри конструкции Попытка...Исключение: если преобразование прошло и результат равен Цел(результат), строка содержит целое число. Учтите, что Число() принимает и дробные строки вида «12.5», поэтому одного отсутствия ошибки недостаточно — сравнение с целой частью обязательно.

Чем Цел() отличается от Окр()?

Цел() отбрасывает дробную часть в сторону нуля: Цел(2.9) = 2. Окр() округляет по правилам арифметики: Окр(2.9, 0) = 3. Для проверки на целое обе функции подходят одинаково, разница важна только когда нужен сам результат преобразования.

Работает ли проверка с отрицательными числами?

Да. Сравнение Значение = Цел(Значение) корректно работает для отрицательных значений: -5 = Цел(-5) даст Истина, -5.4 = Цел(-5.4) даст Ложь. Оператор % также корректно обрабатывает отрицательные операнды при проверке на ноль.

Как проверить в запросе, что число целое?

В языке запросов нет функции Цел(), поэтому обычно выбирают данные запросом, а проверку выполняют уже в коде при обходе выборки. Если нужно отсечь дробные значения на уровне запроса, используют выражение с ВЫРАЗИТЬ(Поле КАК ЧИСЛО(разрядность, 0)) и сравнение с исходным полем.

Почему сравнение 0.1 + 0.2 = 0.3 может дать неожиданный результат?

В 1С числа хранятся в десятичном виде, поэтому классическая проблема двоичной арифметики выражена слабее, но при делении и промежуточных расчётах разрядность результата ограничена, и возможны округления. Если проверка на целое применяется к результату вычислений, сначала округлите его функцией Окр() до рабочей разрядности.

Как запретить ввод дробных чисел в реквизит без кода?

В конфигураторе откройте свойства реквизита и в типе Число установите разрядность дробной части равной нулю. Платформа автоматически будет отбрасывать или не принимать дробную часть при вводе, и дополнительная проверка в коде потребуется только для программно заполняемых значений.