Процедура распределения ошибки

1. aet 55 04.07.13 12:19 Сейчас в теме
Добрый день!
В каких-нибудь типовых ПП 1С есть такое?
Пример:

ТабличнаяЧасть(ФИО - Процент из 100):
Петров 33.35
Сидоров 33.35
Кузнецов 33.35

Ошибка = 100 - Итог("Процент") = -0.05;

Процедура РаспределитьОшибку(ТабличнаяЧасть, "Процент", Ошибка).

ТабличнаяЧасть(ФИО - Процент):
Петров 33.33
Сидоров 33.33
Кузнецов 33.34

Спасибо!
По теме из базы знаний
Вознаграждение за ответ
Показать полностью
Найденные решения
14. СергейКа 670 04.07.13 14:14 Сейчас в теме
(13) Как хотите :)
Только в вашем простом так же не будет работать, если сумму не удастся распределить с первого раза.
Плюс типовая все же универсальнее.
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. echo77 1920 04.07.13 12:26 Сейчас в теме
(1) Из-за предварительного просмотра? Напиши в супорт?

В чем проблема написать самому?
6. aet 55 04.07.13 12:48 Сейчас в теме
(3) echo77, проблемы написать нет, просто не первый раз сталкиваюсь, вдруг велосипед.
2. aet 55 04.07.13 12:20 Сейчас в теме
И еще по ходу вопрос возник почему у меня раздел всегда слетает на Life? )
4. СергейКа 670 04.07.13 12:28 Сейчас в теме
Есть нечто подобное в ЗУП для распределения погрешностей округления в РСВ-1.
5. СергейКа 670 04.07.13 12:32 Сейчас в теме
Процедура ОкруглитьСлагаемыеПоСумме(Данные, ИмяКолонки, Сумма, Точность = 0, ИмяКлюча = "ФизЛицо") Экспорт 
	
	ВременнаяТаблица = Данные.Скопировать(, ИмяКлюча + "," + ИмяКолонки);
	ВременнаяТаблица.Колонки.Добавить(ИмяКолонки + "Окр");
	Для каждого СтрокаТЗ Из ВременнаяТаблица Цикл
		СтрокаТЗ[ИмяКолонки + "Окр"] = Окр(СтрокаТЗ[ИмяКолонки],Точность)
	КонецЦикла;
	Данные.ЗагрузитьКолонку(ВременнаяТаблица.ВыгрузитьКолонку(ИмяКолонки + "Окр"),ИмяКолонки);
	
	СуммаСлагаемых = ВременнаяТаблица.Итог(ИмяКолонки + "Окр");
	Если СуммаСлагаемых <> Сумма Тогда
		Шаг = Pow(10, -Точность);
		РасхождениеСуммы = Сумма - СуммаСлагаемых;
		Приращение = ?(РасхождениеСуммы > 0, Шаг, -Шаг);
		ВсегоПриращений = Мин(РасхождениеСуммы / Приращение, ВременнаяТаблица.Количество());
		ВременнаяТаблица.Колонки.Добавить(ИмяКолонки + "Расхождение");
		ВременнаяТаблица.Колонки.Добавить(ИмяКолонки + "Изменение");
		Для каждого СтрокаТЗ Из ВременнаяТаблица Цикл
			СтрокаТЗ[ИмяКолонки + "Расхождение"] = ?(СтрокаТЗ[ИмяКолонки + "Окр"] < СтрокаТЗ[ИмяКолонки], СтрокаТЗ[ИмяКолонки] - СтрокаТЗ[ИмяКолонки + "Окр"], СтрокаТЗ[ИмяКолонки + "Окр"] - СтрокаТЗ[ИмяКолонки]);
			СтрокаТЗ[ИмяКолонки + "Изменение"] = ?(СтрокаТЗ[ИмяКолонки + "Окр"] < СтрокаТЗ[ИмяКолонки], - Шаг, Шаг);
		КонецЦикла;
		ВременнаяТаблица.Сортировать(ИмяКолонки + "Изменение" + ?(Приращение > 0,""," Убыв") + ", " + ИмяКолонки + "Расхождение Убыв");
		СтруктураПоиска = Новый Структура(ИмяКлюча); 
		Для Сч = 1 По ВсегоПриращений Цикл
			Если ВременнаяТаблица[Сч-1][ИмяКолонки + "Изменение"] <> Приращение Тогда
				ЗаполнитьЗначенияСвойств(СтруктураПоиска, ВременнаяТаблица[Сч-1]);
				Данные.НайтиСтроки(СтруктураПоиска)[0][ИмяКолонки] = ВременнаяТаблица[Сч-1][ИмяКолонки + "Окр"] + Приращение;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

КонецПроцедуры
Показать
7. aet 55 04.07.13 13:05 Сейчас в теме
(5) СергейКа, без изменений процедура не решает задачу к сожалению
8. СергейКа 670 04.07.13 13:24 Сейчас в теме
(7) Почему?
Данные - таблица с физлицами и суммами
ИмяКолонки - колонка с суммой
Сумма - целевая сумма
С остальными параметрами думаю понятно.
9. aet 55 04.07.13 13:32 Сейчас в теме
(8) СергейКа, примерно так и сделал:
Сумма - это не ошибка, а правильный итог по колонке, ошибка считается в процедуре.
тз = ТабличнаяЧасть1.Выгрузить();
ОкруглитьСлагаемыеПоСумме(тз, "Руб", 100, 2,"ФИО");
ТабличнаяЧасть1.Загрузить(тз);

__получил:
Петров 33.34
Сидоров 33.34
Кузнецов 33.34
10. aet 55 04.07.13 13:51 Сейчас в теме
(9) проблема в том, что процедура делает только один проход.
11. СергейКа 670 04.07.13 13:55 Сейчас в теме
(9) Точность зависит от количества циклов.
То же пишу и увидел что нашли :)
Пример в приложенной обработке
Прикрепленные файлы:
ВнешняяОбработка1.epf
13. aet 55 04.07.13 14:05 Сейчас в теме
(11) СергейКа, я тоже подумал, что так можно решить, но это немного извращение :)
И в случае когда ФИО не заполнено, результат (при одном проходе, на вашем примере не пробовал) такой:
33.34 33.35 33.35
Буду свое простое, удобное использовать:
Процедура РаспределитьОшибкуКопейки(ТЧ, ИмяКолонки, СуммаИтог) Экспорт
	
	Ошибка = Окр(СуммаИтог - ТЧ.Итог(ИмяКолонки), 2);	
	Если Ошибка = 0 Тогда
		Возврат;
	КонецЕсли;
		
	Шаг = ?(Ошибка < 0, -0.01, 0.01);
	
	КолСтр = ТЧ.Количество()-1;
	Для сч=0 По КолСтр Цикл
		ТЧ[сч][ИмяКолонки] = ТЧ[сч][ИмяКолонки] + Шаг;
		Ошибка = Ошибка - Шаг;
		Если не Ошибка Тогда
			Прервать;
		КонецЕсли;
		сч = ?(сч = КолСтр, -1, сч);
	КонецЦикла;
	
КонецПроцедуры
Показать
14. СергейКа 670 04.07.13 14:14 Сейчас в теме
(13) Как хотите :)
Только в вашем простом так же не будет работать, если сумму не удастся распределить с первого раза.
Плюс типовая все же универсальнее.
15. aet 55 04.07.13 14:16 Сейчас в теме
(14) СергейКа, у меня пока не распределится не выйдет из цикла.
Типовая мощнее конечно, но для данной задачи слишком неудобная :)
16. dusha0020 1120 04.07.13 15:34 Сейчас в теме
(15) aet, Ну как хотите:) Мелким шагом большие таблицы гонять, наверное все-таки долго.
А я вот так это вижу. В один проход:
Процедура РаспределитьОшибку(Таб,ИДколонки,Ошибка,ОкруглятьДо = Неопределено)
	НакопленоОкруглением = 0;
	ТекИтог = 0;
	Итог = Таб.Итог(ИдКолонки) - Ошибка;
	мЦелевой  = Таб.ВыгрузитьКолонку(ИДколонки);
	МаксИнд = мЦелевой.ВГраница();
	ТочностьОкр = ?(НЕ ОкруглятьДо = Неопределено,Pow(10,-ОкруглятьДо),"");
	Кф = 1 - Ошибка / Итог ;
	Для инд = 0 По МаксИнд Цикл
		Если Инд = МаксИнд Тогда мЦелевой[инд] = Итог - ТекИтог; Продолжить КонецЕсли;	
		текЗнач = мЦелевой[инд]*Кф;
		Если НЕ ОкруглятьДо = Неопределено Тогда
			НакопленоОкруглением = НакопленоОкруглением  + ТекЗнач - Окр(ТекЗнач,ОкруглятьДо);
			Если НакопленоОкруглением > ТочностьОкр Тогда
				ТекЗнач = Окр(ТекЗнач,ОкруглятьДо) + ТочностьОкр;
				НакопленоОкруглением = НакопленоОкруглением - ТочностьОкр;
			ИначеЕсли НакопленоОкруглением < - ТочностьОкр Тогда
				ТекЗнач = Окр(ТекЗнач,ОкруглятьДо) - ТочностьОкр;
				НакопленоОкруглением = НакопленоОкруглением + ТочностьОкр;
			КонецЕсли;
		КонецЕсли;
		мЦелевой[инд] = ?(ОкруглятьДо = Неопределено,ТекЗнач,Окр(текЗнач,ОкруглятьДо));
		ТекИтог = ТекИтог + мЦелевой[инд];
	КонецЦикла;
    Таб.ЗагрузитьКолонку(мЦелевой,ИДколонки);
КонецПроцедуры
Показать


P.S. и к тому же пропорционально начальным значениям.
Прикрепленные файлы:
Распределялка.epf
17. aet 55 05.07.13 04:12 Сейчас в теме
(16) dusha0020, на моей реальной задаче распределить нужно копейки, и в большинстве случаев хватит 1го прохода.
Да, для общей задачи, конечно желательно, заранее вычислить дельту, а не бегать с наименьшим шагом.
А вот это в конце огорчило:
и к тому же пропорционально начальным значениям

Пропорции не нужно, ошибку делим по-братски.
12. aet 55 04.07.13 13:59 Сейчас в теме
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот