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

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

Как отделить дробную часть от целой в 1С

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

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

Ключевой момент, который нужно понять сразу: дробная часть вычисляется как разность между исходным числом и его целой частью. Формула выглядит так: ДробнаяЧасть = Число - Цел(Число). Для положительных чисел всё просто, для отрицательных есть нюанс, связанный с тем, как Цел() обрабатывает знак.

Ниже разобраны рабочие варианты кода для встроенного языка 1С, способ получить дробную часть в запросе, поведение функций с отрицательными числами и типичные ошибки, из-за которых копейки «теряются» или округление даёт неожиданный результат.

Какие функции 1С применяются для работы с целой и дробной частью

Во встроенном языке 1С за выделение целой части отвечает функция Цел() (в английском синтаксисе — Int()). Она отсекает дробную часть без округления: Цел(12.75) вернёт 12, Цел(12.25) — тоже 12. Это принципиально отличается от округления.

Функция Окр() (англ. Round()) выполняет именно округление до указанной разрядности: Окр(12.75, 0) даст 13, а Окр(12.25, 0) — 12. Если перепутать эти функции, итоговые суммы в документах начнут расходиться с ожидаемыми значениями.

Дробная часть не имеет собственной функции, поэтому её получают вычитанием: ДробнаяЧасть = Число - Цел(Число). Для 12.75 выражение вернёт 0.75. Чтобы получить дробную часть как целое число (например, копейки из суммы), результат дополнительно умножают на 100 и округляют: Копейки = Окр((Сумма - Цел(Сумма)) * 100, 0).

Базовый способ: выделение целой и дробной части через Цел()

Самый простой и надёжный вариант — вычесть из числа его целую часть. Код выглядит так:

Число = 123.456;

ЦелаяЧасть = Цел(Число); // 123

ДробнаяЧасть = Число - ЦелаяЧасть; // 0.456

Сообщить("Целая: " + ЦелаяЧасть);

Сообщить("Дробная: " + ДробнаяЧасть);

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

Сумма = 1234.56;

Рубли = Цел(Сумма); // 1234

Копейки = Окр((Сумма - Рубли) * 100, 0); // 56

Обратите внимание на Окр() в последней строке. Без округления из-за особенностей двоичного представления дробных чисел можно получить 55.999999 вместо 56 — это приведёт к потере копейки при дальнейшем приведении к целому.

Порядок действий
  1. 1
    Сохраните исходное число в переменную, не перезаписывая его промежуточными результатами
  2. 2
    Получите целую часть: ЦелаяЧасть = Цел(Число)
  3. 3
    Вычислите дробную часть: ДробнаяЧасть = Число - ЦелаяЧасть
  4. 4
    Если нужна дробная часть как целое (копейки, знаки), умножьте на 10/100/1000 и примените Окр()
  5. 5
    Проверьте результат на граничных значениях: 0, отрицательное число, число с нулевой дробной частью

Отличие Цел() от Окр(): когда что использовать

Частая ошибка начинающих разработчиков — использовать Окр(Число, 0) для получения целой части. Это некорректно: Окр(12.7, 0) вернёт 13, тогда как целая часть числа 12.7 — это 12. Разница в одну единицу на каждой строке документа способна дать заметное расхождение в итогах.

ВыражениеЦел()Окр(…, 0)
12.41212
12.51213
12.91213
-12.4-12-12
-12.6-12-13

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

Особенности работы с отрицательными числами

Функция Цел() в 1С отсекает дробную часть в сторону нуля: Цел(-12.75) вернёт -12. Соответственно, выражение Число - Цел(Число) для -12.75 даст -0.75 — дробная часть получится отрицательной.

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

Число = -12.75;

МодульЧисла = ?(Число < 0, -Число, Число);

ЦелаяЧасть = Цел(МодульЧисла); // 12

ДробнаяЧасть = МодульЧисла - ЦелаяЧасть; // 0.75

В расчётах задолженности и возвратов знак обычно обрабатывают отдельно: сначала определяют направление (долг/переплата), затем раскладывают модуль суммы. Это защищает от ситуаций, когда отрицательные копейки «съедают» рубль при формировании печатной формы.

Дробная часть в запросах 1С

В языке запросов 1С нет прямого аналога Цел() для произвольного числа, но есть несколько обходных путей. Наиболее практичный — использование функции ВЫРАЗИТЬ с приведением к числу меньшей разрядности либо вычисление через вычитание с округлением.

Для задач вида «получить копейки от суммы» в запросе часто применяют такую конструкцию:

ВЫБРАТЬ

Продажи.Сумма КАК Сумма,

Продажи.Сумма - ВЫРАЗИТЬ(Продажи.Сумма КАК ЧИСЛО(15, 0)) КАК ДробнаяЧасть

ИЗ

Документ.РеализацияТоваровУслуг КАК Продажи

Приведение ВЫРАЗИТЬ(Сумма КАК ЧИСЛО(15, 0)) отсекает дробную часть на уровне СУБД, и разность даёт дробный остаток. Учтите, что поведение приведения типов может зависеть от используемой СУБД (MS SQL, PostgreSQL, файловый вариант), поэтому результат стоит проверить на тестовых данных именно в вашей среде.

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

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

Практические сценарии применения

Разложение суммы на рубли и копейки

Классическая задача для печатных форм и суммы прописью. Готовый фрагмент:

Функция РазложитьСумму(Сумма)

Результат = Новый Структура;

МодульСуммы = ?(Сумма < 0, -Сумма, Сумма);

Результат.Вставить("Рубли", Цел(МодульСуммы));

Результат.Вставить("Копейки", Окр((МодульСуммы - Цел(МодульСуммы)) * 100, 0));

Возврат Результат;

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

Если копейки после округления оказались равны 100 (пограничный случай из-за представления дробных чисел), добавьте перенос: увеличьте рубли на 1 и обнулите копейки.

Разложение количества на упаковки и остаток

При работе с фасовкой: Цел(Количество / ВУпаковке) даёт число полных упаковок, а Количество % ВУпаковке (оператор остатка от деления) — остаток штук. Для 25 штук по 6 в упаковке получится 4 упаковки и 1 штука.

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

Условие Число = Цел(Число) возвращает Истина только для целых чисел. Это удобно для контроля ввода: если пользователь ввёл количество 2.5 там, где допустимы только целые значения, проверка сразу это покажет.

Маршрут решения

Как выбрать действие

Нужно отсечь дробную часть без округленияИспользуйте Цел(Число)
Нужно округлить до ближайшего целого или разрядаИспользуйте Окр(Число, Разрядность)
Нужны копейки из суммыОкр((Сумма - Цел(Сумма)) * 100, 0)
Нужен остаток от деления целых чиселИспользуйте оператор % (Количество % Делитель)
Разложение выполняется в запросеПрименяйте ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15, 0)) и вычитание

Типичные ошибки и как их избежать

Первая и самая распространённая ошибка — отсутствие округления после вычитания. Из-за двоичного представления дробных чисел выражение (0.56) * 100 может дать 55.9999999999, и последующее Цел() вернёт 55 вместо 56. Всегда завершайте вычисление копеек функцией Окр().

Вторая ошибка — использование строковых функций для разложения числа: поиск точки через Найти() и разбор Лев()/Прав(). Такой код ломается при смене региональных настроек (разделитель может быть запятой), при экспоненциальном представлении больших чисел и при выводе в другом формате. Числовые операции надёжнее и быстрее.

Третья ошибка — забыть про отрицательные значения. Код, отлично работающий на положительных суммах, на возвратах и сторно начинает выдавать отрицательные копейки и неверные печатные формы. Проверяйте разложение на отрицательных тестовых данных.

Типичные ошибки
01
Окр(Число, 0) вместо Цел() — итоги документов расходятся из-за округления вместо отсечения
02
Цел((Сумма - Цел(Сумма)) * 100) без Окр — из-за двоичного представления теряется копейка
03
Разбор числа строковыми функциями — код ломается при смене разделителя дробной части
04
Игнорирование отрицательных чисел — на возвратах появляются отрицательные копейки
05
Потеря исходного значения: число перезаписывается целой частью до вычисления дробной

Проверка результата

После внедрения кода проверьте его на контрольном наборе значений: целое число (100), число с одним знаком (12.5), число с копейками (1234.56), ноль, отрицательное значение (-99.99) и граничный случай с девятками (0.999). Сумма целой и дробной части должна точно сходиться с исходным числом.

Для финансовых расчётов полезен дополнительный контроль: разложите сумму на рубли и копейки, затем соберите обратно (Рубли + Копейки / 100) и сравните с исходным значением. Расхождение больше 0.005 сигнализирует об ошибке в логике округления.

Контрольные точки

Как проверить результат

Сумма частей
Норма

Целая + Дробная = исходное число

Тревожный признак

Расхождение даже на 0.01

Копейки из 1234.56
Норма

Рубли = 1234, Копейки = 56

Тревожный признак

Копейки = 55 или 57

Отрицательное число -12.75
Норма

Модуль разложен на 12 и 0.75

Тревожный признак

Отрицательные копейки в печатной форме

Целое число 100
Норма

Дробная часть = 0

Тревожный признак

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

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

Есть ли в 1С готовая функция «ДробнаяЧасть»?

Нет, отдельной функции нет. Дробную часть получают выражением Число - Цел(Число). Для копеек добавляют умножение на 100 и Окр().

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

Цел() отсекает дробную часть без округления: Цел(12.9) = 12. Окр() округляет до ближайшего значения: Окр(12.9, 0) = 13. Для разложения сумм нужен Цел(), для округления — Окр().

Почему копейки получаются на единицу меньше?

Причина — двоичное представление дробных чисел: 0.56 100 может дать 55.9999..., и Цел() отсечёт до 55. Решение — применять Окр((Сумма - Цел(Сумма)) 100, 0).

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

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

Как узнать, является ли число целым?

Сравните число с его целой частью: условие Число = Цел(Число) истинно только для целых значений. Это удобно для контроля ввода и проверки делимости.

Как работает Цел() с отрицательными числами?

Цел() отсекает дробную часть в сторону нуля: Цел(-12.75) = -12. Если нужна положительная дробная часть, раскладывайте модуль числа, а знак обрабатывайте отдельно.

Итог

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

Дробная часть в 1С вычисляется как Число - Цел(Число). Цел() отсекает, Окр() округляет — не путайте их в финансовых расчётах. Копейки получайте через Окр((Сумма - Цел(Сумма)) * 100, 0), отрицательные суммы раскладывайте по модулю, а в запросах используйте ВЫРАЗИТЬ с проверкой поведения на своей СУБД.