Проверка числа на целое во встроенном языке 1С
Содержание
Самый короткий способ: сравните число с его целой частью — Число = Цел(Число). Если равенство истинно, дробной части нет, число целое. Второй по частоте приём — остаток от деления на единицу: Число % 1 = 0. Оба работают и для положительных, и для отрицательных значений.
Ошибка, с которой приходят чаще всего: ищут отдельный «целый тип». В 1С его нет. Любое числовое значение имеет тип Число, и 3 и 3.5 — это один и тот же тип. «Целое» здесь означает не тип данных, а математическое свойство: дробная часть равна нулю. Поэтому проверка всегда сводится к арифметике, а не к ТипЗнч.
Ниже — рабочие методы: от быстрой однострочной проверки до валидации пользовательского ввода в форме и анализа поля в запросе. С примерами и числами, которые можно пересчитать.
Функция Цел и сравнение с исходным значением
Цел(Число) отбрасывает дробную часть и возвращает целую. Отбрасывание идёт «в сторону нуля»: Цел(7.9) = 7, Цел(-7.9) = -7. Это не округление — 7.9 не превращается в 8.
На этом и строится проверка:
Если Число = Цел(Число) Тогда
Сообщить("Число целое");
Иначе
Сообщить("У числа есть дробная часть");
КонецЕсли;
Разберём на значениях:
Цел(10)=10→10 = 10→ целое ✅Цел(10.0)=10→10 = 10→ целое ✅Цел(10.4)=10→10.4 = 10ложь → дробное ❌Цел(-3.2)=-3→-3.2 = -3ложь → дробное ❌
Метод надёжен тем, что не зависит от знака и не чувствителен к направлению отбрасывания: для любого дробного значения Цел вернёт другое число, и сравнение даст Ложь.
Для положительных чисел целую часть даёт и Окр(Число, 0, 0) — округление до нуля знаков в меньшую сторону. Но у Окр сложнее поведение с отрицательными и с режимами округления, поэтому для проверки «целое или нет» берите именно Цел — он однозначен.
Остаток от деления через оператор %
В языке 1С есть оператор взятия остатка — знак %. 17 % 5 = 2. Если делить на единицу, остаток и есть дробная часть по модулю:
Если Число % 1 = 0 Тогда
// дробной части нет — число целое
КонецЕсли;
Проверка на примерах:
17 % 1=0→ целое ✅17.25 % 1=0.25→ дробное ❌-4.5 % 1=-0.5→ дробное ❌
Знак остатка в 1С наследуется от делимого, поэтому для -4.5 результат отрицательный. Для проверки это не мешает: сравнение идёт с нулём, а -0.5 нулю не равно.
Какой из двух способов выбрать? Оба эквивалентны по результату. Число = Цел(Число) читается нагляднее и чаще встречается в чужом коде. % 1 = 0 короче, когда остаток вам нужен ещё и для чего-то другого (например, проверить кратность: Число % 2 = 0 — чётное, Число % 10 = 0 — кратно десяти).
| Метод | Запись | Когда удобнее |
|---|---|---|
| Сравнение с целой частью | Число = Цел(Число) | читаемость, универсальность |
| Остаток от деления | Число % 1 = 0 | рядом уже нужна проверка кратности |
Почему проверять тип «Число» бесполезно
Логично ждать, что раз есть функция ТипЗнч, то ей можно отличить целое от дробного. Нельзя. ТипЗнч(3) и ТипЗнч(3.7) оба вернут Тип("Число") — платформа не хранит «целость» как признак типа.
ТипЗнч полезна в другом: убедиться, что перед вами вообще число, а не строка, дата или Неопределено. Это важно, когда значение пришло «снаружи» — из реквизита формы, из прочитанного файла, из внешнего обмена:
Если ТипЗнч(Значение) <> Тип("Число") Тогда
Сообщить("Это не число — проверять на целое нечего");
Возврат;
КонецЕсли;
Если значение лежит в строке ("10", "10,5"), сначала приведите его к числу функцией Число(). Учтите разделитель: во встроенном языке дробная часть отделяется точкой, а строка из интерфейса или файла может содержать запятую. Перед преобразованием замените её:
Текст = СтрЗаменить(Текст, ",", ".");
ЧисловоеЗначение = Число(Текст);
Если строку с запятой передать в Число() без замены, вы получите ошибку преобразования или усечённое значение — проверьте формат до разбора.
Большие числа, округление и точность
Частый страх — «плавающая запятая»: вдруг 0.1 + 0.2 даст 0.30000000004 и проверка соврёт. В 1С этого не происходит. Тип Число — десятичный с фиксированной точностью, а не двоичный double, поэтому классические артефакты двоичной арифметики здесь не всплывают: 0.1 + 0.2 в 1С равно ровно 0.3.
Откуда тогда дробная часть у «целого» результата? Из деления. 10 / 3 не делится нацело, платформа округлит частное до рабочей точности, и получится длинная дробь вроде 3.3333333. Для проверки это даже удобно: Цел(3.3333333) = 3, сравнение даёт Ложь, число честно признаётся дробным.
Опасность в обратном — в преждевременном округлении. Если промежуточный результат вы уже округлили до двух знаков, то 3.335 могло стать 3.34 ещё до вашей проверки, и «целость» вы проверяете у не того значения. Правило простое: проверяйте на целое исходную величину, а не уже округлённую.
У числовых реквизитов и у типа Число есть разрядность — заданное число знаков. Если результат вычисления не помещается в разрядность реквизита, при записи он округлится. Поэтому «целое» переменной в памяти и «целое» после сохранения в реквизит — не всегда одно и то же. Проверяйте то значение, с которым реально работаете дальше.
Для очень больших значений держите в уме предел точности платформы: у чисел огромной разрядности крайние младшие цифры могут потеряться при вычислениях. Если считаете, например, суммы с копейками по многомиллионным оборотам, сверяйте результат, а не полагайтесь на то, что он «обязан» быть целым.
Проверка пользовательского ввода в форме
Когда число вводит человек, целость удобнее не ловить постфактум, а сразу не дать ввести лишнее. Два уровня защиты.
Уровень формата. У реквизита-числа на форме есть свойство Формат. Поставьте число дробных цифр ЧДЦ=0 — поле перестанет принимать дробную часть, пользователь физически не введёт 3,5. Это самый дешёвый способ, когда по смыслу поля дроби быть не должно (количество штук, число сотрудников, номер).
Уровень проверки. Если дроби в поле допустимы, но в конкретной операции нужно целое, проверьте значение в обработчике. Подходят два события:
ПриИзмененииреквизита — реагировать сразу после ввода.ОбработкаПроверкиЗаполнения— проверить перед записью или перед выполнением команды.
Пример проверки при изменении поля Количество:
&НаКлиенте
Процедура КоличествоПриИзменении(Элемент)
Если Объект.Количество <> Цел(Объект.Количество) Тогда
Предупреждение = "Количество должно быть целым числом";
ПоказатьПредупреждение(, Предупреждение);
Объект.Количество = Цел(Объект.Количество);
КонецЕсли;
КонецПроцедуры
Здесь после предупреждения значение ещё и обрезается до целого — это один из вариантов; иногда правильнее не трогать ввод, а просто не дать записать документ. Тогда проверку выносят в ОбработкаПроверкиЗаполнения и добавляют ошибку в массив, чтобы платформа подсветила поле.
Текст кнопки и само название события могут чуть отличаться между типовыми конфигурациями, но свойство Формат с параметром ЧДЦ и событие ПриИзменении есть в любой форме управляемого приложения.
Как проверить целое значение в запросе
Во встроенном языке есть Цел и оператор %. В языке запросов 1С — нет ни того, ни другого. Поэтому целую часть в запросе получают приведением типа через ВЫРАЗИТЬ:
ВЫБРАТЬ
Остатки.Количество КАК Количество,
ВЫБОР
КОГДА Остатки.Количество = ВЫРАЗИТЬ(Остатки.Количество КАК ЧИСЛО(15, 0))
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК ЦелоеЛиКоличество
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 0)) приводит значение к числу без дробных знаков. Нюанс: приведение в запросе округляет, а не отбрасывает. 3.6 станет 4, а не 3. Для нашей задачи это не мешает — сравнение Количество = ВЫРАЗИТЬ(...) даёт Истина только тогда, когда значение и так было целым: любое дробное после округления отличается от исходного.
Если нужно именно отобрать строки с дробным количеством, поставьте условие в ГДЕ:
ГДЕ
Остатки.Количество <> ВЫРАЗИТЬ(Остатки.Количество КАК ЧИСЛО(15, 0))
Первый аргумент разрядности (15) берите с запасом под ваши значения, второй (0) — это ноль дробных знаков, он и отсекает дробную часть при округлении.
Готовая функция и типичные ошибки
Чтобы не писать проверку каждый раз, вынесите её в общий модуль:
Функция ЭтоЦелоеЧисло(Знач Значение) Экспорт
Если ТипЗнч(Значение) <> Тип("Число") Тогда
Возврат Ложь;
КонецЕсли;
Возврат Значение = Цел(Значение);
КонецФункции
Функция сначала отсекает нечисловые значения (Строка, Неопределено, Дата), а затем сравнивает с целой частью. Вызов читается однозначно: Если ЭтоЦелоеЧисло(Остаток) Тогда ....
Где чаще всего ошибаются:
- 🔸 Ждут отдельный целый тип.
ТипЗнчне отличает3от3.7. Проверять нужно арифметикой, а не типом. - 🔸 Путают
Целс округлением.Цел(2.9)=2, а не3. Для «целого ближайшего» нуженОкр, а неЦел. - 🔸 Проверяют уже округлённое значение. Если величину округлили раньше, проверка покажет «целое» там, где исходное число было дробным.
- 🔸 Сравнивают строку с числом.
"10" = Цел(10)дастЛожь— слева строка. СначалаЧисло(), и не забыть про запятую-разделитель. - 🔸 Ищут
Целв языке запросов. Там работаетВЫРАЗИТЬ(... КАК ЧИСЛО(15, 0)), причём с округлением, а не отбрасыванием.
Если проверяете пришедшее извне значение (обмен, файл, HTTP-ответ), не доверяйте тому, что это число. Сначала ТипЗнч или аккуратное Число() с обработкой исключения, и только потом — проверка на целое.
Где проверка на целое нужна на практике
Проверка редко бывает самоцелью — обычно она защищает следующий шаг. Несколько типовых ситуаций.
Штучный товар. Нельзя отгрузить 2,5 монитора. Перед проведением документа проверяют количество по позициям со штучной единицей измерения и не дают записать дробь. Здесь уместнее всего формат ЧДЦ=0 на поле количества плюс контроль в ОбработкаПроверкиЗаполнения.
Деление на равные части. Сумму раздают по сотрудникам, месяцам, партиям. Если Сумма % ЧислоЧастей <> 0, деление неровное, и остаток надо куда-то отнести — обычно к последней части. Проверка на целое показывает, появится ли «хвост» в копейках.
Нумерация и коды. Порядковые номера, коды строк, табельные номера по смыслу целые. Дробное значение в таком поле — почти всегда следствие ошибки в расчёте выше по коду, и отловить его лучше сразу, а не на этапе печати.
Импорт из файла. В загружаемой таблице количество или число периодов может прийти как 3.0, 3, "3,00". После приведения к числу проверка на целое отсекает строки, которые заполнили неверно, до того как они попадут в документ.
Во всех случаях логика одна: привели значение к числу → убедились, что это число (ТипЗнч) → сравнили с Цел. Отличается только реакция — предупредить, обрезать, отклонить запись или перенести остаток.
Частые вопросы
Чем `Цел` отличается от `Окр`?
Цел отбрасывает дробную часть в сторону нуля: Цел(2.9) = 2, Цел(-2.9) = -2. Окр округляет по правилам и может дать 3. Для проверки «целое или нет» берите Цел.Как проверить, что число кратно, например, пяти?
Число % 5 = 0. Проверка на целое — частный случай с делителем 1.Почему `ТипЗнч` не видит, целое число или дробное?
Число. «Целость» это не тип, а свойство значения (дробная часть равна нулю), поэтому проверяется только вычислением.Как в запросе отобрать только дробные значения?
Поле <> ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 0)). Приведение убирает дробную часть, и неравенство оставляет строки, где она была.Строка `"12,5"` — как проверить её на целое?
СтрЗаменить), затем Число(), и только потом сравнивайте с Цел. Без замены разделителя преобразование может сломаться.