|  04.09.2007, 15:14 | #1 | 
| Участник | Алгоритм расчета общей суммы 
			
			Граждане форумчане, Помогите составить алгоритм рассчета общей суммы. Вкратце опишу проблему на примере: Формируется отчет, в котором выводятся строки документа с указанием кол-ва, цены и суммы по строке. По этим суммам рассчитывается итоговая сумма документа. Фиксированно кол-во по строке и исходная сумма (в отчет не попадает). Все суммы округляются до 2ого знака после запятой. Цена (расчетная) рассчитывается как Сумма (исходная) / Кол-во Сумма (расчетная) рассчитывается как Цена (расчетная) * Кол-во Пример: Итого, 9 копеек разницы. Необходимо: Менять цену так, чтобы свести к минимуму расхождение общей суммы. Последний раз редактировалось kashperuk; 04.09.2007 в 15:18. Причина: картинку вставил | 
|  | |
| За это сообщение автора поблагодарили: petr (2). | |
|  04.09.2007, 15:20 | #2 | 
| Banned | 
			
			Цифры 3.34 и 6.63 заранее известны? Если да, то сравнивайте расчетную и исходную накопленные суммы по каждой строке: Delta1 = 3,34 - decRound(3,34/10, 2) = 3,34 - 3,30 = 0,04 decRound(Delta1/10, 2) = decRound(0,004, 2) = 0 => коррекция невозможна Delta2 = 3,34 + 6,63 - 3,30 - 6,60 = 0,07 decRound(Delta2/10, 2) = decRound(0,007, 2) = 0,01 => коррекция = +0,01 => цена = 0,67 Последний раз редактировалось EVGL; 04.09.2007 в 15:27. | 
|  | 
|  04.09.2007, 15:21 | #3 | 
| Участник | 
			
			Да, конечно. Известно кол-во по строке, правильная (до округления) сумма по строке, и, соответственно, правильная (без округления) общая сумма. | 
|  | 
|  04.09.2007, 15:32 | #4 | 
| Banned | 
			
			Тогда см. предыдущий пост. Возможно, надо будет еще обработку последней строки вставить, чтобы оставшаяся ошибка включалась в последнюю расчетную сумму (если это возможно, что последняя "Сумма расчетная" != "Цена расчетная" * "Количество"). Проще говоря: 10 ----- 0,67 ----- 6,67 (!= 6,70) ----- 6,63 Последний раз редактировалось EVGL; 04.09.2007 в 15:35. | 
|  | 
|  04.09.2007, 16:02 | #5 | 
| Участник | Цитата: 
		
			Менять цену так, чтобы свести к минимуму расхождение общей суммы.
		
	 | 
|  | 
|  04.09.2007, 16:06 | #6 | 
| Участник | 
			
			Да. То есть разница между 10.00 и 9.97 будет уже 0.03, а не 0.07. То есть пытаемся уменьшить общее отклонение итоговой суммы | 
|  | 
|  04.09.2007, 16:13 | #7 | 
| Участник | Цитата: суммы всегда храняться с большим числом знаков. суммы всегда отображаются в отчете с округлением. Рассчитывать итоговую сумму по НЕОРУГЛЕННЫМ суммам - большая методическая ошибка. Перед выводом, перед записью в БД, любая сумма должна быть округлена при помощи Currency::amount(...) или Currency::amountCur(...). Это правило. Кстати, любое количество также должно быть округлено перед выводом и перед записью в БД. | 
|  | 
|  04.09.2007, 16:17 | #8 | 
| Banned | 
			
			Тот алгоритм, который я описал, используется в русской книге продаж в случае "НДС по оплате" с несколькими оплатами к одной накладной. Нетрудно видеть, что ошибка в моем алгоритме <= 0,01 * Среднее_количество_по_строке ~ 0,10 в вашем случае.
		 | 
|  | 
|  04.09.2007, 16:18 | #9 | 
| Участник | 
			
			Ну тогда вам в математический справочник. Идея, насколько я помню такая: У вас есть числа A1, A2, An (в вашем примере это 3,34 и 6,63). Вам надо найти такие числа B1, B2, Bn (в вашем случае это сумма округлвения), чтобы выполнялось два условия. 1-ое условие: (А1/Х1 - В1)*100 - целое число. (Х1 - это кол-во для первой строки 10). Второе условие: Сумма (В1*Х1 + В2*Х2 + Вn*Хn) - (А1 + А2 + Аn) стремиться к нулю (причем по модулю). Т.е. задача на минимизацию. Я думаю такие задачи решаютмя в численных методах, или может еще в каком разделе математики. Подумаю вечерком, может что сам еще вспомню, но тут скорее надо литературу по этой теме искать или знакомых математиков трясти. | 
|  | |
| За это сообщение автора поблагодарили: kashperuk (3). | |
|  04.09.2007, 16:19 | #10 | 
| Banned | Цитата: 
		
			Сообщение от mazzy
			   По-моему, уже сказали. Но еще раз: суммы всегда храняться с большим числом знаков. суммы всегда отображаются в отчете с округлением. Рассчитывать итоговую сумму по НЕОРУГЛЕННЫМ суммам - большая методическая ошибка. Перед выводом, перед записью в БД, любая сумма должна быть округлена при помощи Currency::amount(...) или Currency::amountCur(...). Это правило. Кстати, любое количество также должно быть округлено перед выводом и перед записью в БД. | 
|  | 
|  04.09.2007, 16:21 | #11 | 
| Участник | Цитата: | 
|  | 
|  04.09.2007, 16:23 | #12 | 
| Banned | |
|  | 
|  04.09.2007, 16:24 | #13 | 
| Участник | 
			
			Вот немного усложненный пример, на котором можно думать   Расхождение в этом случае = 11.29 2 mazzy: Да оно так и хранится. Проблема в том, что цены округлены до второго знака тоже. и бухгалтерия не хочет видеть более 2 знаков в цене. А соответственно возникают расхождения. P.S. Именно, EVGL правильно говорит   | 
|  | 
|  04.09.2007, 16:30 | #14 | 
| Участник | Цитата: Посмотрите настройку валюты на закладке Округление. Обычно достаточно там настроить: цены округлять до сотой доли единицы валюты и т.д. Или, речь о закупках? Откуда такая забавная задачка? | 
|  | 
|  04.09.2007, 16:33 | #15 | 
| Участник | 
			
			to Михаил Андреев, mazzy Да вполне нормальная задача. Посмотрите как получаются отклонения в основной валюте, это практически тоже самое. Только там никто разницу не оптимизирует, а просто она кидается на счет расхождений в основной валюте и все. А kashperuk хочет в своем отчете эту разницу немного оптимизировать, т.е. уменьшить | 
|  | 
|  04.09.2007, 16:33 | #16 | 
| Участник | Цитата: Не факт, что так и ХРАНИТСЯ. Аксапта всегда ПОКАЗЫВАЕТ округленные суммы, а ХРАНИТ как записал программист. Точно-точно? Ну и пусть ВИДИТ! Если же вопрос не о представлении, а о ХРАНЕНИИ. У цен свое правило округления задается в параметрах валют. У цен свой тип, для которого можно настроить свое количество знаков после запятой. Но тогда у бухов будет расхождение с контрагентами, которые работают с двумя знаками после запятой в цене  Если цена округляется, то согласен с EVGL, будут нестыковки либо в цене каждой строчки, либо в общем НДСе в зависимости от того, в каком направлении будет выполняться расчет (от цены к общей сумме или от общей суммы к цене) | 
|  | |
| За это сообщение автора поблагодарили: kashperuk (3). | |
|  04.09.2007, 16:38 | #17 | 
| Banned | 
			
			Мой вариант: 0.33 --- 0.67 --- 0.23 --- 2.10 => 271.50. Да, хреново. 0.33 --- 0.67 --- 0.24 --- 2.05 => 280.75 гораздо лучше. | 
|  | |
| За это сообщение автора поблагодарили: kashperuk (3). | |
|  04.09.2007, 16:43 | #18 | 
| Banned | 
			
			Самый тупой вариант - это на каждом шаге попробовать изменить цену на -0,01 и +0,01 соответственно, посмотреть, что будет. Т.е. порядка 2^(количество_строк -1) итераций.
		 | 
|  | 
|  04.09.2007, 17:11 | #19 | 
| Участник | 
			
			Есть, кстати, еще одно условие, усложняющее в значительной мере алгоритм   Цена не должна уменьшаться/увеличиваться более, чем на 10% от своего начального значения. Отослал данные для анализа знакомому профессору. Если ничего умного не придумает до завтра, будем сами изобретать какой-то много-итерационный алгоритм. Спасибо всем за участие. Продолжение следует... | 
|  | 
|  04.09.2007, 17:17 | #20 | 
| Участник | Цитата: 
		
			Спасибо всем за участие.
		
	 | 
|  |