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

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

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

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

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

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

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

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

Функция Цел(Число) возвращает целую часть числа, отбрасывая дробную. Для положительных значений она работает как «округление вниз»: Цел(12.75) вернёт 12. Соответственно, дробная часть вычисляется так:

Число = 12.75;

ДробнаяЧасть = Число - Цел(Число); // результат: 0.75

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

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

Если Число <> Цел(Число) Тогда

Сообщить("Количество должно быть целым!");

КонецЕсли;

bsl
Число = 12.75;
ДробнаяЧасть = Число - Цел(Число); // 0.75

Отрицательные числа: почему Цел() даёт неожиданный результат

Функция Цел() в 1С отбрасывает дробную часть в сторону нуля, то есть Цел(-12.75) вернёт -12. Тогда -12.75 - (-12) = -0.75 — дробная часть получается отрицательной. В некоторых задачах это приемлемо, но чаще требуется значение 0.75 или -0.25 в зависимости от логики.

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

Функция ДробнаяЧасть(Число)

Знак = ?(Число < 0, -1, 1);

Возврат (?(Число < 0, -Число, Число) - Цел(?(Число < 0, -Число, Число))) * Знак;

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

Такая функция возвращает -0.75 для -12.75 и 0.75 для 12.75, сохраняя знак исходного числа. Если по логике задачи дробная часть всегда должна быть неотрицательной (например, доля упаковки), знак можно не возвращать.

Альтернативные способы получения дробной части

Через функцию Окр()

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

ЦелаяЧасть = Окр(Число, 0, РежимОкругления.Окр15как10);

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

Учтите: Окр15как10 — это арифметическое округление, поэтому Окр(12.75, 0, ...) вернёт 13, а не 12. Для выделения именно целой части этот режим не подходит — используйте Цел(). Окр() полезен, когда дробную часть нужно сразу округлить до нужной точности, например до копеек: ДробнаяЧасть = Окр(Число - Цел(Число), 2).

Через строковое представление

Иногда встречается приём: преобразовать число в строку и взять часть после разделителя. Этот способ хрупок — разделитель зависит от региональных настроек (точка или запятая), а форматирование может добавить разделители групп разрядов. Использовать его в расчётах не следует; он допустим разве что для отображения, и то с осторожностью.

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

Число - Цел(Число)

Основной вариант для положительных чисел. Быстро и наглядно. Для отрицательных даёт отрицательную дробную часть.

По модулю с возвратом знака

Универсально для любых значений, требует обёртки в функцию. Рекомендуется в общих модулях.

Окр(Число - Цел(Число), N)

Когда дробную часть нужно сразу округлить до копеек или заданной точности.

Строковый разбор

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

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

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

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

Сумма = 1234.56;

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

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

Умножение на 100 с последующим округлением обязательно: без Окр() из-за двоичного представления чисел можно получить 55.999999 вместо 56 копеек.

Упаковки и штуки

При работе с фасовкой дробная часть показывает неполную упаковку. Например, если в упаковке 12 штук, а отгружается 30, то Цел(30/12) = 2 полные упаковки, а дробная часть частного помогает вычислить остаток: 30 - 2 * 12 = 6 штук. Для таких задач часто удобнее остаток от деления через %: Остаток = 30 % 12.

Часы и минуты в учёте времени

Длительность 7.5 часа — это 7 часов и 30 минут. Минуты получают умножением дробной части на 60 с округлением: Минуты = Окр((Длительность - Цел(Длительность)) * 60, 0).

Порядок действий при реализации
  1. 1
    Определите, могут ли входные числа быть отрицательными
  2. 2
    Для положительных используйте Число - Цел(Число)
  3. 3
    Для смешанных значений оберните вычисление в функцию с обработкой знака
  4. 4
    Если результат идёт в денежный расчёт — округлите через Окр() до нужной разрядности
  5. 5
    Проверьте функцию на граничных значениях: 0, 1.0, -1.5, 0.1 + 0.2

Особенности точности дробных чисел в 1С

Числа в 1С хранятся с ограниченной точностью, и простые десятичные дроби вроде 0.1 не представляются точно. Поэтому сравнение дробной части с нулём напрямую может дать ложный результат: (0.1 + 0.2) - Цел(0.1 + 0.2) не всегда равно в точности 0.3.

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

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

Если Макс(ДробнаяЧасть, -ДробнаяЧасть) < 0.000001 Тогда

// считаем число целым

КонецЕсли;

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

Типичные ошибки и их последствия

Наиболее частая ошибка — применение Окр(Число, 0) вместо Цел(Число) для получения целой части. При значении 12.5 и выше в дробной части округление даст 13, и дробная часть станет отрицательной: 12.6 - 13 = -0.4. В расчёте остатков это даёт отрицательные количества и сбои в проведении документов.

Вторая ошибка — забыть округлить копейки после умножения дробной части на 100. Третья — игнорировать отрицательные входные данные, когда функция пишется «для цен», а потом переиспользуется для корректировок и возвратов, где суммы отрицательные.

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

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

Быстрее всего проверить выражение в конфигураторе: остановитесь в отладке и вычислите Число - Цел(Число) в окне «Вычислить выражение». Для регрессионной проверки полезно прогнать функцию на наборе значений: 0, 1, 0.5, -0.5, 12.75, -12.75, 0.1+0.2.

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

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

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

Целая + дробная часть
Норма

Сумма равна исходному числу с допуском

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

Расхождение больше 0.000001 — ошибка в формуле

Модуль дробной части
Норма

Меньше 1

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

Равен 1 или больше — использовано округление вместо Цел()

Знак для отрицательных чисел
Норма

Соответствует логике задачи и задокументирован

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

Знак теряется или появляется неожиданно

Часто задаваемые вопросы

Есть ли в 1С встроенная функция для дробной части?

Нет, отдельной функции нет. Стандартный приём — вычесть целую часть: Число - Цел(Число). Для повторного использования удобно написать собственную функцию в общем модуле.

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

Цел() отбрасывает дробную часть, всегда двигаясь к нулю: Цел(12.9) = 12. Окр() выполняет арифметическое округление: Окр(12.6, 0) = 13. Для выделения целой части нужна именно Цел().

Как получить копейки из суммы?

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

Почему дробная часть получается отрицательной?

Это происходит либо для отрицательных чисел (Цел(-12.75) = -12, итог -0.75), либо при ошибочном использовании Окр() вместо Цел() для положительных чисел больше x.5. Решение — вычисление по модулю с сохранением знака.

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

Сравните число с его целой частью: Число = Цел(Число). Для надёжности с учётом погрешности используйте допуск: Макс(Д, -Д) < 0.000001, где Д — дробная часть.

Можно ли получить дробную часть через остаток от деления?

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

Итог

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

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