Форум: "Основная";
Текущий архив: 2003.12.23;
Скачать: [xml.tar.bz2];
ВнизСуммирование чисел Найти похожие ветки
← →
Pilot (2003-12-09 18:47) [0]Доброе время суток!
Возникла проблема с суммированием чисел:
есть число разбитое на 3 части при их сложении результат либо больше, либо меньше на 0.01, 0.02.
Подскажите как от этого избавиться(в смысле как правильно сложить без ошибок)?
Всем заранее спасибо!!!
← →
Cosinus (2003-12-09 18:50) [1]???
Что такое "разбитое на 3 части"???
← →
Тимохов (2003-12-09 18:51) [2]Подробнее, пожалуйста.
← →
Pilot (2003-12-09 19:12) [3]
> Cosinus © (09.12.03 18:50) [1]
> Тимохов (09.12.03 18:51) [2]
Eсть число 240:
1. 240/1,26=190,476190
2. 190,476190*0,2=38,095238
3. 190,476190*0,06=11,428571
Если их сложить то получается 239,999999 при округленнии должно получиться 240.00. А программа выдает 239.99. А при 4-х единицах по 240.00 960.00.
← →
panov (2003-12-09 19:16) [4]Первое правило суммирования - округляется сумма, а не слагаемые.
← →
Кот Бегемот (2003-12-09 19:17) [5]Это потому что ты делишь неправильно
240/1.26 ~ 190,47619047619047619047619047619(476190)
почувствуйте разницу !!!
← →
Тимохов (2003-12-09 19:26) [6]Вопрос, все-таки, не очень ясен.
← →
Pilot (2003-12-09 19:35) [7]
> panov © (09.12.03 19:16) [4]
Мне необходимо вывести сумму и все слогаемы так, чтобы их сумма была равной показанной. Точность должна быть 2 знака после запятой. Аобщую сумму "правильную" я могу получить.
> Кот Бегемот © (09.12.03 19:17) [5]
> Это потому что ты делишь неправильно
> 240/1.26 ~ 190,47619047619047619047619047619(476190)
> почувствуйте разницу !!!
Я это знаю но при округлении до сотых используется 3-ий знак после запятой, а остальные не учитываются.
Поэтому мне необходимо округлить все слогаемые и просуммировать их, но так чтобы сумма была правильная.
← →
Тимохов (2003-12-09 19:37) [8]Общий подход такой: если надо некую сумму разбить на слагаемые так, что их сумма равна исходной сумме, то нужно последнее слагаемое считать как исходная сумма минус сумма всех слагаемых.
← →
panov (2003-12-09 19:42) [9]Ошибка в 17-й строке.
← →
Pilot (2003-12-09 19:43) [10]
> Тимохов (09.12.03 19:37) [8]
Спасибо, но делов том, что при таком подходе может считаться неправильно одно из слогаемых, а выбрать какое из них трудно, т.е. все слогаемые должны считаться правильно.
← →
Тимохов (2003-12-09 19:52) [11]Правильно все только в раю.
А в дискретном мире (мире компов) всегда что-то неправильно...
← →
Pilot (2003-12-09 20:01) [12]
> panov © (09.12.03 19:42) [9]
Да я знаю.
← →
Pilot (2003-12-10 18:26) [13]Вот исходник как я это делал
Вариант1:
sum1:=0;
sum2:=0;
sum3:=0;
summ:=0;
Dm.qNDS.First;
for i:=1 to Dm.qNDS.RecordCount do
begin
{sum1:=sum1+Dm.qNDS.FieldByName("PF").AsFloat*Dm.qNDS.FieldByName("Kol").AsFloat;
sum2:=sum2+Dm.qNDS.FieldByName("NDS").AsFloat*Dm.qNDS.FieldByName("Kol").AsFloat;
sum3:=sum3+Dm.qNDS.FieldByName("Price").AsFloat*Dm.qNDS.FieldByName("Kol").AsFloat;}
summ1:=Dm.qNDS.FieldByName("PF").AsFloat+Dm.qNDS.FieldByName("NDS").AsFloat+Dm.qNDS.FieldByName("Price").AsFloat;
summ:=summ+summ1*Dm.qNDS.FieldByName("Kol").AsFloat;
Dm.qNDS.Next;
end;
//Sum:=FormatFloat("0.000",sum3);
//Sum:=FormatFloat("0.00",StrToFloat(Sum));
rez:=FormatFloat("0.00",summ);
summ:=StrToFloat(rez);
//sum1:=StrToFloat(FormatFloat("0.00",sum1));
//sum2:=StrToFloat(FormatFloat("0.00",sum2));
//sum:=FormatFloat("0.00",summ-sum1-sum2);
rez:="";
Transform(rez,summ{sum1+sum2+sum3},0);
s:=Trim(rez);
lProp:=s;
Вариант2:
sum1:=sum1+Dm.qNDS.FieldByName("PF").AsFloat*Dm.qNDS.FieldByName("Kol").AsFloat;
sum2:=sum2+Dm.qNDS.FieldByName("NDS").AsFloat*Dm.qNDS.FieldByName("Kol").AsFloat;
sum3:=sum3+Dm.qNDS.FieldByName("Price").AsFloat*Dm.qNDS.FieldByName("Kol").AsFloat;
summ1:=Dm.qNDS.FieldByName("PF").AsFloat+Dm.qNDS.FieldByName("NDS").AsFloat+Dm.qNDS.FieldByName("Price").AsFloat;
summ:=summ+summ1*Dm.qNDS.FieldByName("Kol").AsFloat;
sum1:=StrToFloat(FormatFloat("0.00",sum1));
sum2:=StrToFloat(FormatFloat("0.00",sum2));
Dm.qNDSAll1.Value:=StrToFloat(FormatFloat("0.00",summ-sum1-sum2));
Подскажите пожалейста где ошибка, если есть, или что я неправильно делаю.
Всем заранее большое спасибо!!!
← →
Тимохов (2003-12-10 18:36) [14]А что собственно нужно сделать?
Сложно по постановке этого и всех предыдущих вопросов понять что вообще ты хочешь?
← →
Тимохов (2003-12-10 18:37) [15]Опиши по пунктам: хочу добиться того-то и того-то. Как мне это сделать?
На такой вопрос намного легче отвечать.
← →
Sandman25 (2003-12-10 18:38) [16]Ошибка в том, что при добавлении к сумме, надо округлять добавляемое значение до двух знаков после запятой.
← →
Pilot (2003-12-10 19:19) [17]
> Sandman25 © (10.12.03 18:38) [16]
Когда я округляю до двух знаков то общая сумма "бьет" на 0,01.
Почему я не знаю.
> Тимохов (10.12.03 18:37) [15]
1. Есть число(240).
2. Считаем число с которым работаем(240/1,26=190,47619047619047619047619047619)
x=190,47619047619047619047619047619
3. Считаем 20% от числа(y=x*0,2=38,095238095238095238095238095238)
4. Считаем 6% от числа (z=x*0,06=11,428571428571428571428571428571)
x+y+z=239,9999999999999999999999999999
Вопрос в том как правильно округлить, чтобы ошибка(0,01) пропала и встала в нужном слагаемом.
Т.к. если округлять до 2-х знаков получается следующее:
190,48+38,10+11,43=240,01.
Вот такай вопрос.
Заранее большое спасибо!!!
← →
Тимохов (2003-12-10 19:25) [18]Насколько я понимаю это НДС и НП (или что-то типа того)?
Если ты хошь добиться точности, то этого сделать никак нельзя.
Всегда будет ошибка.
Я уже писал ранее (сам занимаюсь финансовыми системами), что в аналогичном случае выбирается жертва, котрая считается не по понятиям, а путем вычитания из общей суммы всех слагаемых кроме последнего.
В твоем случае я бы следал так.
1. Посчитал делением х и округлил бы его до 2 знаков (типа, копейки)
2. Посчитал умножением у и округлил бы его до 2 знаков (типа, тоже копейки)
3. Почитал z = 240-x-y.
Тогда все будет верно. Можешь жертвой выбрать другое слагаемое.
Вообще говоря, по другому ты никак не сделаешь - это общий подход, который используется во всех финансовых системах.
← →
Тимохов (2003-12-10 19:28) [19]я в своей практике жертвой выбираю сумму без НДС и НП, т.е. в твоем изложении это х.
← →
Pilot (2003-12-10 19:51) [20]
> Тимохов (10.12.03 19:28) [19]
Делов том что, если выбирать жертвой сумму без НДС и НП, т.е. это х, то при нескольких х сумма без НДС может отличаться от реальной суммы. Этот способ я пробовал и мне сказали, что такое решение проблемы не подходит.Вот.
← →
Тимохов (2003-12-10 19:55) [21]Ну бейтесь дальшей, упрямые.
Я тебе сказал - других решений нет.
Всегда что-то будет неточно.
Могу говорить об этом вполне уверено - лимон строк бухгалтерской системы на дельфи и фигова туча на sql, и конечно, успешная эксплуатация всего комплекса не первый год, хорошее доказательство этого.
Другое решение, может заключаться в том, что отталкиваться надо не от суммы с НДС и НП, а от суммы без НДС и НП. Т.е. х сделать хранимой в базе и вводимой пользователем. Тогда проблем точно не будет.
← →
Anatoly Podgoretsky (2003-12-10 20:00) [22]Именно неверный алгоритм, отсюда и проблемы и отсутсвие решения.
← →
Тимохов (2003-12-10 20:04) [23]Не очень понял кому это "Именно неверный алгоритм, отсюда и проблемы и отсутсвие решения." многоуважаемого Аналолия.
Но если это к автору вопроса, то я с ним согласен.
Из какой суммы без НДС и НП можно получить число 240? Такого числа с двумя знаками после запятой точно нет.
Здесь дырки в логике... однозначно.
← →
Anatoly Podgoretsky (2003-12-10 20:11) [24]Конечно к автору вопроса, и по логике, надог добавляется к стоимости, а не наоборот, или в России не так?
← →
Pilot (2003-12-10 20:11) [25]
> Тимохов (10.12.03 19:55) [21]
Я так и сделал, т.е.в базе хранится информация о сумме без НДС и от него пляшут все расчеты. Но это не помогает.
Вот эти числа:
Dm.qNDS.FieldByName("PF").AsFloat=Dm.qNDS.FieldByName("Price").AsFloat*0,06
Dm.qNDS.FieldByName("NDS").AsFloat=Dm.qNDS.FieldByName("Price").AsFloat*0,2,
а Dm.qNDS.FieldByName("Price").AsFloat это цена без НДС и НП.
← →
panov (2003-12-10 20:13) [26]1. Где округлять - см. panov © (09.12.03 19:16) [4]
2. Ткни пальцем, пожалуйста, в каком месте ты вообще округляешь?
← →
Тимохов (2003-12-10 20:18) [27]Все-таки Панов прав: ты округляешь то где?
Посчитал НДС, округли.
Посчитал НП, округли.
Потом сложи сумму без НДС и НП, сумму НДС и сумму НП. Получишь сумму с НДС и НП.
Конечно, если ты начнешь сумму с НДС и НП обратно разварачивать в сумму без НДС и НП, то скорее исходную сумму не получишь, но ты этого и не делай.
В общем-то в чем проблема? Зачем тебе понадобилось обратное действие делать?
← →
Anatoly Podgoretsky (2003-12-10 20:27) [28]Обратное действие смысл не имеет, вот пример A:=1/3, a*3
← →
Anatoly Podgoretsky (2003-12-10 20:29) [29]Тимохов (10.12.03 20:18) [27]
При том округление наверняка по закону до целых, до копейки, цента, сантима и т.д..
← →
Тимохов (2003-12-10 20:30) [30]Anatoly Podgoretsky © (10.12.03 20:27) [29]
Я имел в виду до двух знаков после запятой.
← →
Anatoly Podgoretsky (2003-12-10 20:31) [31]То есть до 0.01 копейки?
← →
Anatoly Podgoretsky (2003-12-10 20:31) [32]То есть до 0.01 копейки?
← →
panov (2003-12-10 20:32) [33]Специально провел последовательно все операции в соответствии с panov © (09.12.03 19:16) [4].
Результат(без округлений) такой:
x=190,47619047619048200000000
y=38,09523809523809490000000
z=11,42857142857142880000000
Summa=240,00000000000000500000000
Далее, воспользовавшись функцией округления
FormatFloat("0.00",Round((Summa+0.0005)*100)/100);
получаем значение 240.00
← →
panov (2003-12-10 20:34) [34]А если тебе обязательно нужно использовать числа x,y,z, то в этом случае обязательно будет погрешность.
Её прибавляют к одному из значений(как правило).
← →
Тимохов (2003-12-10 20:39) [35]Anatoly Podgoretsky © (10.12.03 20:31) [31]
Ну я так понял, что целое это рубль. Значит два знака после запятой для целого, это 1 коп.
panov © (10.12.03 20:34) [34]
Полностью согласен с тем, что погрешность куда нибудь прибавляют.
← →
Pilot (2003-12-11 17:13) [36]
> Тимохов (10.12.03 20:18) [27]
При подсчете я округляю следующим образом:
1.Сумма без НДС и НП 190,48
НДС 190,48*0,2=38,10(38,096)
НП 190,48*0,06=11,43(11,4288)
Сумма 240,01
2.Сумма без НДС и НП 190,48*2=380,96
НДС 380,96*0,2=76,19(76,1904)
НП 380,96*0,06=22,86(22,85712)
Сумма 480,01
И если считать Сумму без НДС и НП по формуле
Сумма - НДС - НП, то получаю
1.Сумма без НДС и НП 190,47
2.Сумма без НДС и НП 190,48*2=380,95
Т.о. видна ошибка при подсчете суммы.
Как поступить в таком случае?
Заранее благодарен!!!
← →
Тимохов (2003-12-11 17:17) [37]Сущай, ты уже просто издеваешься - тебе тут массу всего сказали, прочти все внимательно и сделай выводы сам. Повторяться не хочется - все равно будет то же самое.
← →
PIlot (2003-12-11 17:27) [38]Всем большое спасибо за помощь!
Я понял что больше ничего толкового не подскажут.
← →
BorisKb (2003-12-11 17:32) [39]Если не привязываться к НДС и НП (например идет счет и суммирование по людям), то еще один вариант, используемый мной. Это "по копейке сверху" или "по копейке снизу". Т.е. Разницу округления по 0,01 раскидываю по отдельным слагаемым, нужным образом отсортированным.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.12.23;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.008 c