Проблема с округлением слагаемых
От: Аноним  
Дата: 27.09.13 12:31
Оценка:
double d1 = 2.1348;
double d2 = 2.1349;

fprintf( stderr, "d1=%.2f, d2=%.2f, d1+d2=%.2f\n", d1, d2, d1+d2 );


В результате имеем:
d1=2.13, d2=2.13, d1+d2=4.27

Считается все правильно и точно, но визуально результаты не совпадают.
И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?
Re: Проблема с округлением слагаемых
От: dead0k  
Дата: 27.09.13 12:36
Оценка: 1 (1) +4 -1
Здравствуйте, Аноним, Вы писали:

А>Поскольку речь идет о деньгах...

Догадываешься почему никто не хранит деньги в числах с плавающей точкой?
Re: Проблема с округлением слагаемых
От: Evgeny.Panasyuk Россия  
Дата: 27.09.13 12:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Проблема вообще решаема?


Fixed-point arithmetic
Re[2]: Проблема с округлением слагаемых
От: Vzhyk  
Дата: 27.09.13 12:51
Оценка:
27.09.2013 15:36, dead0k пишет:

> А>Поскольку речь идет о деньгах...

> Догадываешься почему никто не хранит деньги в числах с плавающей точкой?
А может он остатки себе на счет переводит, ждет когда за ним придут.
Posted via RSDN NNTP Server 2.1 beta
Re: Проблема с округлением слагаемых
От: rg45 СССР  
Дата: 28.09.13 08:48
Оценка: +2
Здравствуйте, Аноним, Вы писали:

А>
А>double d1 = 2.1348;
А>double d2 = 2.1349;

А>fprintf( stderr, "d1=%.2f, d2=%.2f, d1+d2=%.2f\n", d1, d2, d1+d2 );
А>


А>В результате имеем:

А>d1=2.13, d2=2.13, d1+d2=4.27

А>Считается все правильно и точно, но визуально результаты не совпадают.

А>И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?

Тут уже вспомнили о проблемах использования чисел с плавающей точкой, в частности для операций с денежными суммами... Но на мой взгляд, в данном случае проблема в другом. Тебя беспокоит, что "визуально результаты не совпадают". Другими словами, ты хочешь, чтобы суммы округленных и не округленных величин были равны? Думаю, ты сам понимаешь, что это невозможно в общем случае. И просто переход от чисел с плавающей точкой к числам с фиксированной точкой эту проблему также не решает. Тебе нужно определиться со своими бизнес-целями, с тем что именно ты хочешь получить в результате.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Проблема с округлением слагаемых
От: vladimir_i СССР  
Дата: 28.09.13 20:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>...

А>Считается все правильно и точно, но визуально результаты не совпадают.
А>И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов. Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?

А почему просто не выводить все знаки? Котировки валют, например, могут запросто иметь 4 знака после запятой.
Re: Проблема с округлением слагаемых
От: Кодт Россия  
Дата: 29.09.13 00:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Считается все правильно и точно


Правильно? ТОЧНО?
С каких пор 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);


Финансово-отчётный подход: каждое слагаемое заранее округлить, точно посчитать сумму (например, в фиксированной арифметике, либо дав гарантии, что ошибки плавающей арифметики в итоге будут меньше ошибки округления), и вывести результат, подогнанный под выведенные слагаемые.
А набежавшую ошибку положить к себе в карман. (Для этого нужно правильно округлять, разумеется, — а то можно в минус уйти).

Финансово-бессеребренничный подход: посчитать сумму точных слагаемых, посчитать сумму округлённых слагаемых, найти разность — ошибку сложения; раскидать эту ошибку округления по округлённым слагаемым; вывести подправленные округлённые слагаемые и округлённую сумму.
Набежавшую ошибку округления суммы (до полукопейки) положить в шапку нищему на паперти.
Перекуём баги на фичи!
Re: Проблема с округлением слагаемых
От: pagid Россия  
Дата: 29.09.13 10:29
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

А>Считается все правильно и точно, но визуально результаты не совпадают.

А>И чем больше слагаемых, тем больше может быть расхождение. Поскольку речь идет о деньгах, у заказчика, клиентов и налоговой возникает куча ненужных вопросов.
Если речь о деньгах каково происхождение d1 = 2.1348 и d2 = 2.1349 ?

А> Если округлять до двух знаков перед сложением, результат не будет совпадать с итоговой суммой, получаемой из базы. Проблема вообще решаема?

Что хранится в базе и почему суммы должны совпасть?
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[2]: Проблема с округлением слагаемых
От: pagid Россия  
Дата: 29.09.13 10:42
Оценка: 1 (1) +1 -1
Здравствуйте, dead0k, Вы писали:

D>Догадываешься почему никто не хранит деньги в числах с плавающей точкой?

Совсем по другим причинам.
И ничем фиксированная точка проблеме ТС не поможет.

P.S. И вопрос у него не о С/С++, а о правилах и проблемах округления в предметной области.
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[2]: Проблема с округлением слагаемых
От: avpavlov  
Дата: 29.09.13 12:21
Оценка:
Здравствуйте, dead0k, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>Поскольку речь идет о деньгах...

D>Догадываешься почему никто не хранит деньги в числах с плавающей точкой?

Ну т.е. если он 2.1348 и 2.1349 переложит в точный тип данных, то сумма округленных величин начнет совпадать с округленной суммой?
Re[3]: Проблема с округлением слагаемых
От: Evgeny.Panasyuk Россия  
Дата: 29.09.13 13:42
Оценка:
Здравствуйте, pagid, Вы писали:

D>>Догадываешься почему никто не хранит деньги в числах с плавающей точкой?

P>Совсем по другим причинам.
P>И ничем фиксированная точка проблеме ТС не поможет.

Без фиксированной точки у него могут быть проблемы даже без округления.
Re[4]: Проблема с округлением слагаемых
От: avpavlov  
Дата: 29.09.13 13:52
Оценка:
EP>Без фиксированной точки у него могут быть проблемы даже без округления.

Давай в студию пример для чисел из реальной жизни (а не граничных значений double)
Re[5]: Проблема с округлением слагаемых
От: Evgeny.Panasyuk Россия  
Дата: 29.09.13 14:44
Оценка:
Здравствуйте, avpavlov, Вы писали:

EP>>Без фиксированной точки у него могут быть проблемы даже без округления.

A>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)

http://ideone.com/IsCuWE
Re[4]: Проблема с округлением слагаемых
От: pagid Россия  
Дата: 29.09.13 15:13
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Без фиксированной точки у него могут быть проблемы даже без округления.

В финансово-бухгалтерских расчетах только в очень редких случаях.
В целом все будет упираться в вопрос с какой точностью проводить вычисления и в какой момент округлять. Числа с фиксированной точкой от этих проблем не избавят.
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[6]: Проблема с округлением слагаемых
От: pagid Россия  
Дата: 29.09.13 15:23
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>http://ideone.com/IsCuWE

Нужно ли из этого сделать вывод, что числа с плавающей точкой использовать нельзя?
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[6]: Проблема с округлением слагаемых
От: avpavlov  
Дата: 29.09.13 15:34
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, avpavlov, Вы писали:


EP>>>Без фиксированной точки у него могут быть проблемы даже без округления.

A>>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)

EP>http://ideone.com/IsCuWE


Ну это да, я уже и забыл когда такие числа через == сравнивал, уже на автомате делаю через сравнение разницы с эпсилон
Re[6]: Проблема с округлением слагаемых
От: avpavlov  
Дата: 29.09.13 15:35
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, avpavlov, Вы писали:


EP>>>Без фиксированной точки у него могут быть проблемы даже без округления.

A>>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)

EP>http://ideone.com/IsCuWE


Ну и контр пример

http://ideone.com/f8ELDf
Re[5]: Проблема с округлением слагаемых
От: Evgeny.Panasyuk Россия  
Дата: 29.09.13 17:48
Оценка:
Здравствуйте, pagid, Вы писали:

EP>>Без фиксированной точки у него могут быть проблемы даже без округления.

P>В финансово-бухгалтерских расчетах только в очень редких случаях.

Ну вот тебе финансовая задачка — тебя надо купить некий stuff и ещё что-то, берёшь соответственную сумму, покупаешь stuff — а на что-то уже не хватает :
#include <iostream>
 
int main()
{
    using namespace std;
    double money = 0.0,
    stuff = 9.1,
    etc = 4.12;
     
    money += stuff;
    money += etc;
     
    money -= stuff;
    if(money < etc)
        cout << "GTFO!" << endl;
}



P>В целом все будет упираться в вопрос с какой точностью проводить вычисления и в какой момент округлять. Числа с фиксированной точкой от этих проблем не избавят.

EP>>Без фиксированной точки у него могут быть проблемы даже без округления.
Re[7]: Проблема с округлением слагаемых
От: Evgeny.Panasyuk Россия  
Дата: 29.09.13 17:50
Оценка:
Здравствуйте, pagid, Вы писали:

EP>>http://ideone.com/IsCuWE

P>Нужно ли из этого сделать вывод, что числа с плавающей точкой использовать нельзя?

Как ты пришёл к такому выводу?
Re[7]: Проблема с округлением слагаемых
От: Evgeny.Panasyuk Россия  
Дата: 29.09.13 17:57
Оценка:
Здравствуйте, avpavlov, Вы писали:

EP>>>>Без фиксированной точки у него могут быть проблемы даже без округления.

A>>>Давай в студию пример для чисел из реальной жизни (а не граничных значений double)
EP>>http://ideone.com/IsCuWE
A>Ну это да, я уже и забыл когда такие числа через == сравнивал, уже на автомате делаю через сравнение разницы с эпсилон

1. Какой именно эпсилон, и как ты сравниваешь (на ==, <, >)?
2. Зачем раскидывать грабли и скакать между ними?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.