Считается все правильно и точно, но визуально результаты не совпадают.
И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?
27.09.2013 15:36, dead0k пишет:
> А>Поскольку речь идет о деньгах... > Догадываешься почему никто не хранит деньги в числах с плавающей точкой?
А может он остатки себе на счет переводит, ждет когда за ним придут.
А>В результате имеем: А>d1=2.13, d2=2.13, d1+d2=4.27
А>Считается все правильно и точно, но визуально результаты не совпадают. А>И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?
Тут уже вспомнили о проблемах использования чисел с плавающей точкой, в частности для операций с денежными суммами... Но на мой взгляд, в данном случае проблема в другом. Тебя беспокоит, что "визуально результаты не совпадают". Другими словами, ты хочешь, чтобы суммы округленных и не округленных величин были равны? Думаю, ты сам понимаешь, что это невозможно в общем случае. И просто переход от чисел с плавающей точкой к числам с фиксированной точкой эту проблему также не решает. Тебе нужно определиться со своими бизнес-целями, с тем что именно ты хочешь получить в результате.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Аноним, Вы писали:
А>... А>Считается все правильно и точно, но визуально результаты не совпадают. А>И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?
А почему просто не выводить все знаки? Котировки валют, например, могут запросто иметь 4 знака после запятой.
Здравствуйте, Аноним, Вы писали:
А>Считается все правильно и точно
Правильно? ТОЧНО?
С каких пор 1/1000 точно представимо в двоичной дроби?
A>но визуально результаты не совпадают.
К ошибкам вычисления добавляется ошибка вывода.
Даже если мы будем не двоичные, а десятичные дроби считать:
0.114 + 0.114 = 0.228
округляем до 2 знаков
~0.11 + ~0.11 = ~0.22 или ~0.23
потому что
0.11±0.005 + 0.11±0.005 = 0.22±0.010 = 0.21...0.23
А>И чем больше слагаемых, тем больше может быть расхождение.
Ну ничего, ничего, переоткрываешь основы вычислительной математики, начало XX века.
A>Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?
Решаема, и многими способами.
Например, можно вместе с результатом выводить и оценку погрешности.
Если у нас N слагаемых, каждое из которых округлено до k-го знака, то ошибка округления каждого — ±0.5E-k, а ошибка суммы — соответственно, ±N*0.5E-k.
Это — физический подход.
float values[10];
float sum = 0, err = 0;
for(i=0; i!=10; ++i)
{
float v = values[i];
float r = floor(v*100+0.5)*0.01;
float e = 0.005;
sum += r;
err += e;
printf("%d-th addend is %f±%f\n", i, r, e);
}
printf("sum is %f±%f\n", sum, err);
Финансово-отчётный подход: каждое слагаемое заранее округлить, точно посчитать сумму (например, в фиксированной арифметике, либо дав гарантии, что ошибки плавающей арифметики в итоге будут меньше ошибки округления), и вывести результат, подогнанный под выведенные слагаемые.
А набежавшую ошибку положить к себе в карман. (Для этого нужно правильно округлять, разумеется, — а то можно в минус уйти).
Финансово-бессеребренничный подход: посчитать сумму точных слагаемых, посчитать сумму округлённых слагаемых, найти разность — ошибку сложения; раскидать эту ошибку округления по округлённым слагаемым; вывести подправленные округлённые слагаемые и округлённую сумму.
Набежавшую ошибку округления суммы (до полукопейки) положить в шапку нищему на паперти.
Здравствуйте, <Аноним>, Вы писали:
А>Считается все правильно и точно, но визуально результаты не совпадают. А>И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов.
Если речь о деньгах каково происхождение d1 = 2.1348 и d2 = 2.1349 ?
А> Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?
Что хранится в базе и почему суммы должны совпасть?
Здравствуйте, dead0k, Вы писали:
D>Догадываешься почему никто не хранит деньги в числах с плавающей точкой?
Совсем по другим причинам.
И ничем фиксированная точка проблеме ТС не поможет.
P.S. И вопрос у него не о С/С++, а о правилах и проблемах округления в предметной области.
Здравствуйте, dead0k, Вы писали:
D>Здравствуйте, Аноним, Вы писали:
А>>Поскольку речь идет о деньгах... D>Догадываешься почему никто не хранит деньги в числах с плавающей точкой?
Ну т.е. если он 2.1348 и 2.1349 переложит в точный тип данных, то сумма округленных величин начнет совпадать с округленной суммой?
Здравствуйте, pagid, Вы писали:
D>>Догадываешься почему никто не хранит деньги в числах с плавающей точкой? P>Совсем по другим причинам. P>И ничем фиксированная точка проблеме ТС не поможет.
Без фиксированной точки у него могут быть проблемы даже без округления.
Здравствуйте, avpavlov, Вы писали:
EP>>Без фиксированной точки у него могут быть проблемы даже без округления. A>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Без фиксированной точки у него могут быть проблемы даже без округления.
В финансово-бухгалтерских расчетах только в очень редких случаях.
В целом все будет упираться в вопрос с какой точностью проводить вычисления и в какой момент округлять. Числа с фиксированной точкой от этих проблем не избавят.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>http://ideone.com/IsCuWE
Нужно ли из этого сделать вывод, что числа с плавающей точкой использовать нельзя?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, avpavlov, Вы писали:
EP>>>Без фиксированной точки у него могут быть проблемы даже без округления. A>>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)
EP>http://ideone.com/IsCuWE
Ну это да, я уже и забыл когда такие числа через == сравнивал, уже на автомате делаю через сравнение разницы с эпсилон
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, avpavlov, Вы писали:
EP>>>Без фиксированной точки у него могут быть проблемы даже без округления. A>>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)
EP>http://ideone.com/IsCuWE
Здравствуйте, pagid, Вы писали:
EP>>Без фиксированной точки у него могут быть проблемы даже без округления. P>В финансово-бухгалтерских расчетах только в очень редких случаях.
Ну вот тебе финансовая задачка — тебя надо купить некий stuff и ещё что-то, берёшь соответственную сумму, покупаешь stuff — а на что-то уже не хватает :
P>В целом все будет упираться в вопрос с какой точностью проводить вычисления и в какой момент округлять. Числа с фиксированной точкой от этих проблем не избавят. EP>>Без фиксированной точки у него могут быть проблемы даже без округления.
Здравствуйте, avpavlov, Вы писали:
EP>>>>Без фиксированной точки у него могут быть проблемы даже без округления. A>>>Давай в студию пример для чисел из реальной жизни (а не граничных значений double) EP>>http://ideone.com/IsCuWE A>Ну это да, я уже и забыл когда такие числа через == сравнивал, уже на автомате делаю через сравнение разницы с эпсилон
1. Какой именно эпсилон, и как ты сравниваешь (на ==, <, >)?
2. Зачем раскидывать грабли и скакать между ними?