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


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

1. Пример исходных данных

Предположим, у нас есть следующая таблица значений:

Количество
1 2
--- ---
2 3
--- ---
3 5
--- ---

Общая сумма: 40 рублей

Общая база распределения (сумма количеств): 2 + 3 + 5 = 10

2. Расчёт коэффициента

Сначала определим коэффициент распределения:

Коэффициент = ОбщаяСумма / ОбщаяБаза

Коэффициент = 40 / 10 = 4

Теперь каждая строка получит:

  • Строка 1: 2 × 4 = 8

  • Строка 2: 3 × 4 = 12

  • Строка 3: 5 × 4 = 20

Итог: 8 + 12 + 20 = 40 — всё корректно, сумма распределена.

3. Что делать при дробных результатах

Если бы база была не делится нацело, например:

Количество
1 1
--- ---
2 2
--- ---
3 3
--- ---

База = 6
Коэффициент = 40 / 6 ≈ 6.666...

Результаты до округления:

  • 1 × 6.666... = 6.666...

  • 2 × 6.666... = 13.333...

  • 3 × 6.666... = 20

Сумма: 6.666... + 13.333... + 20 = 40

Если мы округлим каждое значение:

  • 6.666 → **7
    **
  • 13.333 → **13
    **
  • 20 → **20
    **

Итог: 7 + 13 + 20 = 40 — совпадает.

Но бывают случаи, когда после округления сумма не совпадает. Тогда нужно использовать алгоритм корректировки.

4. Алгоритм с корректировкой

Шаг 1: Расчёт долей и округление вниз

Для каждой строки:

  • вычисляется точное значение: Количество * Коэффициент

  • округляется вниз: ЦелаяСумма = Цел(ТочноеЗначение)

  • сохраняется остаток: Остаток = ТочноеЗначение - ЦелаяСумма

Считаем сумму всех округленных значений: ТекущаяСумма

Шаг 2: Корректировка

Если ТекущаяСумма < ИсходнаяСумма:

  • разницу Недостача = ИсходнаяСумма - ТекущаяСумма

  • отсортировать строки по убыванию остатка (чем больше остаток, тем ближе значение к следующему целому)

  • распределить недостачу по этим строкам — прибавить по 1 рублю в строки с наибольшими остатками, пока не будет достигнута нужная сумма

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

Имеем:

Количество
1 2
--- ---
2 1
--- ---
3 3
--- ---

Сумма: 40
База: 6
Коэффициент: 40 / 6 = 6.666...

Точное распределение:

  • 2 × 6.666... = 13.333 → Цел = 13 → Остаток = 0.333

  • 1 × 6.666... = 6.666 → Цел = 6 → Остаток = 0.666

  • 3 × 6.666... = 20 → Цел = 20 → Остаток = 0

Целые суммы: 13 + 6 + 20 = 39
Осталась 1 рубль недостачи

Сортировка по остаткам:

  1. строка 2 (остаток 0.666)

  2. строка 1 (остаток 0.333)

  3. строка 3 (остаток 0)

Прибавляем 1 рубль строке 2 (у которой самый большой остаток)

Итоговое распределение:

  • строка 1: 13

  • строка 2: 7 (6 + 1)

  • строка 3: 20

Сумма: 40 рублей

6. Реализация в 1С

На языке 1С можно реализовать алгоритм так:

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

7. Применение в реальных задачах

Такой подход нужен при:

  • распределении оплаты между позициями

  • учёте пропорциональных налогов

  • разбиении бонусов/скидок между строками

  • расчёте себестоимости по количеству

Он обеспечивает корректную арифметику и точную итоговую сумму, соответствующую исходной, несмотря на округления.