Как округлить сумму к распределению до рубля?

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

1. Цель округления

При пропорциональном распределении общей суммы (например, 40 рублей) по строкам на основе коэффициента (или количества), сначала вычисляются доли, которые обычно являются дробными числами. Чтобы результаты были удобны для работы в 1С (например, для бухгалтерии), суммы необходимо округлить до целого значения — до рубля.

2. Стандартное округление

В 1С используется встроенная функция:

Окр(Число, КоличествоЗнаков)

Чтобы округлить число до целого рубля:

Окр(Сумма, 0)

Пример:

Строка.СуммаРаспределения = Окр(ОбщаяСумма \* Строка.Коэффициент, 0);

3. Проблема несоответствия итогов

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

  • Окр(40 * 0.3333, 0) = 13

  • Окр(40 * 0.3333, 0) = 13

  • Окр(40 * 0.3333, 0) = 13
    → Всего: 39, а нужно было 40

Или наоборот, если бы округлилось до 14,14,14 → 42

4. Подход к контролю округления

Решение: применить корректировку одной или нескольких строк после округления. Алгоритм:

  1. Распределяем сумму без округления — сохраняем "точные" значения.

  2. Сохраняем также округлённые значения.

  3. Вычисляем разницу между ОкруглённойСуммой и ОбщейСуммой.

  4. Корректируем строки на ±1 рубль так, чтобы свести разницу к нулю.

5. Пример алгоритма округления с корректировкой

ОбщаяСумма = 40;
Точности = Новый ТаблицаЗначений;
Точности.Колонки.Добавить("Индекс");
Точности.Колонки.Добавить("ДробнаяЧасть");
СуммаОкругленная = 0;
Индекс = 0;
Для Каждого Строка Из Таблица Цикл
Доля = ОбщаяСумма \* Строка.Коэффициент;
Строка.Сумма = Окр(Доля, 0);
СуммаОкругленная = СуммаОкругленная + Строка.Сумма;
// Запомним дробную часть для сортировки
Остаток = Доля - Окр(Доля, 0);
НовСтр = Точности.Добавить();
НовСтр.Индекс = Индекс;
НовСтр.ДробнаяЧасть = Остаток;
Индекс = Индекс + 1;
КонецЦикла;
Разница = ОбщаяСумма - СуммаОкругленная;

6. Корректировка на ±1 рубль

Теперь распределим разницу по строкам:

Если Разница > 0 Тогда
// Сортировка по убыванию дробной части (ближе к +1)
Точности.СортироватьПоУбыванию("ДробнаяЧасть");
Для Инд = 0 По Разница - 1 Цикл
Таблица\[Точности\[Инд\].Индекс\].Сумма = Таблица\[Точности\[Инд\].Индекс\].Сумма + 1;
КонецЦикла;
ИначеЕсли Разница < 0 Тогда
// Сортировка по возрастанию дробной части (ближе к 0  можно отнять)
Точности.СортироватьПоВозрастанию("ДробнаяЧасть");
Для Инд = 0 По Модуль(Разница) - 1 Цикл
Таблица\[Точности\[Инд\].Индекс\].Сумма = Таблица\[Точности\[Инд\].Индекс\].Сумма - 1;
КонецЦикла;
КонецЕсли;

7. Что учесть в алгоритме

  • Убедитесь, что количество строк в таблице больше или равно абсолютному значению разницы.

  • При отрицательной разнице — будьте осторожны, чтобы не уйти в отрицательные значения.

  • Корректировка на ±1 происходит только по тем строкам, где это допустимо (например, сумма ≥ 1).

8. Использование числовой точности

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

Этот способ гарантирует, что:

  • Распределение будет корректным и пропорциональным,

  • Сумма после округления строго совпадёт с исходной,

  • Ошибки округления распределены между строками по остаточной дробной части.