Почему функция Окр() в 1С 7.7 возвращает одинаковый результат при разных режимах округления?

Программист 1С v7.7
← На главную

При разработке на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с нюансами работы встроенных математических функций. Одной из самых обсуждаемых является функция Окр(). Начинающие разработчики нередко ожидают, что третий параметр этой функции (способ округления) будет управлять любым округлением, однако на практике сталкиваются с тем, что для числа 34.2875 при округлении до двух знаков результат всегда получается 34.29, независимо от того, указан ли флаг 0 или 1.

В этой статье мы подробно разберем, как именно работает алгоритм округления в «семерке», почему возникают подобные ситуации и какие альтернативные способы управления точностью существуют в системе.

Разбор синтаксиса функции Окр()

Для начала вспомним описание функции из официальной документации 1С 7.7. Синтаксис выглядит следующим образом:

Окр(<Число1>, <Число2>, <Способ>)

Рассмотрим назначение каждого параметра:

  1. Число1 — исходное числовое выражение, которое подлежит обработке.
  2. Число2 — количество знаков дробной части, которые нужно оставить. Если указано отрицательное число, округление происходит в целой части (например, до десятков или сотен).
  3. Способ — режим округления граничных значений. Именно здесь кроется корень непонимания. Значение 0 означает, что 1.5 округляется до 1 (вниз), а значение 1 означает, что 1.5 округляется до 2 (вверх).

Главный секрет: правило «0.5»

Проанализируем ситуацию, описанную в теме. Почему Окр(34.2875, 2, 0) и Окр(34.2875, 2, 1) дают одинаковый результат?

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

Рассмотрим наше число 34.2875. Мы хотим округлить его до 2 знаков после запятой:

В данном случае число 75 в отбрасываемом остатке больше, чем 50 (середина разряда). Согласно стандартным правилам математики, если следующая цифра за округляемым разрядом больше или равна 5, то число округляется в большую сторону. Поскольку 0.0075 больше, чем 0.0050, функция всегда прибавит единицу к младшему сохраняемому разряду. Флаг «Способ округления» здесь просто игнорируется, так как ситуация не является «граничной».

Если бы мы округляли число 34.285, ситуация была бы иной:


// Пример для граничного значения 0.5
Сообщить(Окр(34.285, 2, 0)); // Результат: 34.28 (0.5 округляется вниз)
Сообщить(Окр(34.285, 2, 1)); // Результат: 34.29 (0.5 округляется вверх)

Глобальные настройки округления в Конфигураторе

Если в коде третий параметр функции Окр() не указан вовсе, система не берет его «с потолка». В 1С 7.7 существует глобальная настройка, определяющая поведение системы по умолчанию.

Выясним, где она находится. Откройте Конфигуратор, перейдите в меню «Свойства конфигурации», далее выберите вкладку «Задача». Там вы найдете поле «Округление». Возможные варианты:

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

Как реализовать «чистое» отсечение знаков (округление вниз)

Иногда перед программистом стоит задача не округлить число математически, а просто «отрезать» лишние знаки после запятой. Стандартная функция Окр() для этого не предназначена, так как она всегда стремится к ближайшему целому в зависимости от остатка.

Для реализации отсечения (truncation) мы используем комбинацию умножения, выделения целой части и деления. Рассмотрим этот прием на примере:


// Нам нужно оставить 2 знака без округления
ЧислоДляОбработки = 34.2875;
Результат = Цел(ЧислоДляОбработки * 100) / 100; 
// Результат будет 34.28
Сообщить(Результат);

Алгоритм действий здесь следующий:

  1. Умножаем число на 10 в степени N, где N — количество знаков, которые нужно оставить (в нашем случае 10^2 = 100). Число превращается в 3428.75.
  2. Функция Цел() отбрасывает дробную часть, оставляя 3428.
  3. Делим результат обратно на 100, получая 34.28.

Округление «всегда вверх»

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


// Округление всегда вверх до 2 знаков
ИсходноеЧисло = 34.2811;
РезультатВверх = -Окр(-ИсходноеЧисло, 2, 1);
// Результат будет 34.29
Сообщить(РезультатВверх);

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

Проблема точности вычислений в 1С 7.7

Проанализируем еще один важный аспект. В 1С 7.7 используется десятичная арифметика с фиксированной точкой, но при определенных операциях (особенно связанных с делением или использованием внешних объектов через COM/OLE) могут возникать микроскопические погрешности представления чисел.

Например, число, которое визуально выглядит как 1.25, внутри системы из-за погрешности типа Double (при передаче извне) может превратиться в 1.249999999999. В этом случае Окр(Число, 1, 1) выдаст 1.2 вместо ожидаемых 1.3, потому что число фактически меньше граничного значения 0.5.

Чтобы минимизировать такие риски в сложных расчетах, рекомендуется:

Итоги

Подведем итог нашему исследованию. Функция Окр() в 1С 7.7 работает строго по математическим правилам, а её третий параметр управляет поведением системы исключительно в ситуациях, когда остаток равен ровно 0.5.

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

← На главную