Вот так решена задача в типовой УТ10.3
// Функция выполняет пропорциональное распределение суммы в соответствии
// с заданными коэффициентами распределения
//
// Параметры:
// ИсхСумма - распределяемая сумма
// МассивКоэф - массив коэффициентов распределения
// Точность - точность округления при распределении. Необязателен.
//
//Возвращает:
// МассивСумм - массив размерностью равный массиву коэффициентов, содержит
// суммы в соответствии с весом коэффициента (из массива коэффициентов)
// В случае если распределить не удалось (сумма = 0, кол-во коэф. = 0,
// или суммарный вес коэф. = 0), тогда возвращается значение Неопределено
//
Функция РаспределитьПропорционально(Знач ИсхСумма, МассивКоэф, Знач Точность = 2, ПроверкаНулевыхЗначений=Истина) Экспорт
Если МассивКоэф.Количество() = 0 Или (ПроверкаНулевыхЗначений И ИсхСумма = 0) Или ИсхСумма = Null Тогда
Возврат Неопределено;
КонецЕсли;
ИндексМакс = 0;
МаксЗнач = 0;
РаспрСумма = 0;
СуммаКоэф = 0;
Для К = 0 По МассивКоэф.Количество() - 1 Цикл
МодульЧисла = ?(МассивКоэф[К] > 0, МассивКоэф[К], - МассивКоэф[К]);
Если МаксЗнач < МодульЧисла Тогда
МаксЗнач = МодульЧисла;
ИндексМакс = К;
КонецЕсли;
СуммаКоэф = СуммаКоэф + МассивКоэф[К];
КонецЦикла;
Если СуммаКоэф = 0 Тогда
Возврат Неопределено;
КонецЕсли;
МассивСумм = Новый Массив(МассивКоэф.Количество());
Для К = 0 По МассивКоэф.Количество() - 1 Цикл
МассивСумм[К] = Окр(ИсхСумма * МассивКоэф[К] / СуммаКоэф, Точность, 1);
РаспрСумма = РаспрСумма + МассивСумм[К];
КонецЦикла;
// Погрешности округления отнесем на коэффицент с максимальным весом
Если Не РаспрСумма = ИсхСумма Тогда
МассивСумм[ИндексМакс] = МассивСумм[ИндексМакс] + ИсхСумма - РаспрСумма;
КонецЕсли;
Возврат МассивСумм;
КонецФункции // РаспределитьПропорционально()
Показать
Тут всю погрешность кидают на максимальный коэфициент... что не совсем коректно учитывая отрицательные значения.
Я бы построил алгоритм так:
- находим минимум и максиум значений (-5 и +100).
- сдаивгаем все в плюс... чтобы не было значений ниже 0 (+5 делаем)
- в примере получаются числа от 0...105
- распределяем сумму с максимальной точностью (на выходе массив дробных чисел)
- копируем точный массив распределения суммы и округляем числа до необходимой точности
- считаем погрешность итоговую Погрешность = Сумма - Массив.
далее самое интересное... способ распределения погрешности
первое что приходит в голову
- докидывать к суммам можно только по 1 еденицы точности Например (0,01 = 1 копейка) для точности округляени 2.
- Шаг1. Находим максимальную разнциу округл. и точных коэф.
- Щаг2. Докидываем 0.01 к этому коэфициенту
- Щаг3. Погрешность уменьшилась на 0.01, проверяем если она не равно нулю повторяем шаг1.
Посло того как вся погрешность раскидана.. возвращаем смещение -5.
Готово.