powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / и снова копейки: #define, С++ , Builder 2009 ?
46 сообщений из 46, показаны все 2 страниц
и снова копейки: #define, С++ , Builder 2009 ?
    #39353912
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблемка округления в дебилдере 2009.
Не отвлекаемся на теорию прибл-х вычислений вообще и в компах в частности.
Интересует, влияет ли #define , или конкретно 2009-й дебилдер, или особенности проги, в сочетании с хитрым вычисляемым числом?

Ниже я намеренно привожу чуть больший контекст. Есть описания:
Код: plaintext
1.
2.
3.
#define TO_RUB(X) (((X)-floor(X))>=0.5?ceil(X):floor(X))  - округляем до целых
#define TO_KOP(X) (TO_RUB((X)*100.0f)/100.0f)  - округляем до сотых
double funct(x) {..........} - интересует,  когда   funct(i) возвращает 5665.455


Есть 2 варианта кода:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
  double nds;
  ...
  nds = TO_KOP( nds + TO_KOP( funct(i) ));

и оно же, расписанное более подробно для отладки
  double xx;
  xx=  funct(i) *100.0f;
  nds = TO_KOP( nds + TO_RUB( xx ) /100.0f);


Вопрос в том, почему в рантайм и в отладке
Код: plaintext
1.
2.
1)   TO_KOP( funct(i) ) = 5665.45
2)   TO_RUB( xx ) /100.0f = 5665.46

Это видно по итоговому результату nds в пользовательском окне - там тоже округление, но уже в текстовый вид. Казалось бы эквивалентно, но нет, а почему?

П.С. Ну да, в битовом виде на лету промежуточный рез-т "5665.455" не смотрел. Ну а само оно = 5665.4549999...9986...
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354009
locked
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Похоже дибилдер из вас двоих не компилятор.. Компилятор все правильно тебе говорит. Ненужно округлять посреди расчетов. Округление только конечного результата. при представлении для человека.
Вообще тип money - 4 знака после запятой
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354021
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98П.С. Ну да, в битовом виде на лету промежуточный рез-т "5665.455" не смотрел. Ну а само оно = 5665.4549999...9986...
после расчетов может оказаться 5665.4550000...0011... и тоже будет правильно.
Сравнивай не с 0.5, а с 0.5000000001 или 0.4999999999 не соображу сходу как правильно.

А в целом пофиг как округлится при расчете НДС, главное чтобы всегда было однозначно и остальная математика сходилась в рамках документа.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354194
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98,

ну нельзя деньги считать во float/double, ну нельзя.
Единственное исключение -- финансовые расчёты, когда точность не нужна до копейки.
Есть же в Delphi в VCL decimal какой-то, его и нужно использовать.

авторВопрос в том, почему в рантайм и в отладке

1) TO_KOP( funct(i) ) = 5665.45
2) TO_RUB( xx ) /100.0f = 5665.46

Это видно по итоговому результату nds в пользовательском окне - там тоже округление, но уже в текстовый вид. Казалось бы эквивалентно, но нет, а почему?

П.С. Ну да, в битовом виде на лету промежуточный рез-т "5665.455" не смотрел. Ну а само оно = 5665.4549999...9986...


Потому что даже когда ты в отладчике видишь число, оно уже может быть представлено с погрешностью.
Плавающая арифметика в принципе неточная. Она даже внутри в машине, в регистрах, уже неточно может храниться.
Бессмысленно что-то проверять на "такой/не такой".
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354235
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98,

пробуй так округлять
Код: plaintext
1.
2.
(int)( x * 100.0 + 0.5) / 100.0; // до сотых
(int)( x + 0.5); // до целых

и дай полный исходник теста, попробую посмотреть как mingw себя ведет
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354296
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv, знаю твоё неравнодушие к округлениям, об этом я в курсе ещё с больших машин, когда обрабатывал СПРН.
Переделывать тогда уж сотню файлов и процы в БД, да и саму БД переводить на копейки. Это не вариант.
Вопрос в том, почему дефайн считает не как я думаю, ну или наоборот.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354297
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
locked,
уважаемый, складывать надо в копейках, а не в грошах, иначе столкнётесь с вопросом, почему округлённая сумма не равна сумме округлений.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354306
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TСравнивай не с 0.5, а с 0.5000000001 или 0.4999999999 не соображу сходу как правильно.согласен, мысль здравая. Это уже я сам 0.5 написал. Только вопрос возник, когда сравнение ещё стояло:
X-floor(X) >= ceil(X)-X
И вот хоть убей, в дефайне даёт одно, а при разбивке на этапы другое.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354318
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m_Sla и дай полный исходник теста, попробую посмотреть как mingw себя ведет Совсем полный исходник сложно, т.к. вместо моего funct() стоит что-то вроде A->B->at(i)->nds, всё это в цикле, где последнее nds - на самом деле свойство совсем другого класса, и там тоже суммирование, и оно тоже дёргает функцию, к-рая лезет в БД.

Попробую слепить отдельно стоящий фрагмент.
И конечно же, моё 5665,455 - это не всамоделишнее число, а как мне его кажет отладчик.
О! сначала попробую перед прогоном это число руками влепить и посмотрю.
Так что попозднее.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354332
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И кстати, если кого коробит моё "дебилдер" - это не от того, что сейчас вопрос про округления, и не от того, что вместо функции математического округления он использует т.н. "банковское" округление.
Это относится конкретно к пользуемой мною версии 2009, т.к. его редактор! исходников не только не справляется с русскоязычными коментами, но и часто не различает положение курсора в тексте и в своих думах, а также часто и не предсказуемо зависет, а то и попросту курочит исходники, превращая их в нечто бинарное. Но что есть, то есть.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354392
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivПлавающая арифметика в принципе неточная
арифметика сама по себе точная и в регистрах значения "точные",
беда в том что не всякое вещественное число(десятичная дробь в частности) может быть представлено в IEEE 754
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354397
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98И кстати, если кого коробит моё "дебилдер"2009й действительно совсем кривой был. Либо 2007, либо 2010
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354446
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилMasterZivПлавающая арифметика в принципе неточная
арифметика сама по себе точная и в регистрах значения "точные",
беда в том что не всякое вещественное число(десятичная дробь в частности) может быть представлено в IEEE 754


нет, арифметика тоже неточная.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354450
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98MasterZiv, знаю твоё неравнодушие к округлениям, об этом я в курсе ещё с больших машин, когда обрабатывал СПРН.
Переделывать тогда уж сотню файлов и процы в БД, да и саму БД переводить на копейки. Это не вариант.


ты можешь хоть всю жизнь идти к северному полюсу по магнитному компасу, но все равно не дойдешь...

exp98Вопрос в том, почему дефайн считает не как я думаю, ну или наоборот.

не глядел твои макросы , если не устраивает, используй функции, в чем проблема?

шаблонные, если надо. они отлаживаются.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354459
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98,
чтобы понять, что там у тебя, нужен полный код.
полный , рабочий код.

нужно знать типы данных всех переменных и то, как ты их выводишь.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354480
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv,
все они double, и методы возвращают double, проверено неоднократно. Когда-то оставались float, ош. сразу вылезали при числах больше 7 цифр.
Я выберу время на простой пример, и если воспроизведётся, то запостю.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354583
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
3 варианта кода, разные результаты
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
#include <iostream.h>

#define TO_RUB(A) (((A)-floor(A))>=0.5?ceil(A):floor(A))
#define TO_KOP(A) (TO_RUB((A)*100.0f)/100.0f)

double NDS (int k);
//-------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
    int k;
    k= *argv[1] - '0';
    double nd= NDS( k);
    std::cout << nd << endl;
return 0;
}
//-------------------------------------------------------

double NDS ( int k)
{
        double nds = 0.0;
        double xx, yy= 5665.455;

        //int k=3;
        if(k==1) {  //// 1) ответ 5665,45
            xx= yy;
            nds = TO_KOP( nds + TO_RUB( xx *100.0f) /100.0f);
                nds= TO_RUB( xx*100.0f );
        } else if (k==2) {  //// 2) ответ 5665,46
            xx= yy *100.0f;
            nds = TO_KOP( nds + TO_RUB( xx ) /100.0f);
                nds= TO_RUB( xx );
        } else if (k==3) {  //// 3)   ответ 5665,45
            xx= yy;
            nds = TO_KOP( nds + TO_KOP( xx ));
                nds= TO_KOP( xx );
        }//end_if
    return nds;
}

...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354610
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivнет, арифметика тоже неточная.
что значит "неточная"?
десятичная - тож окажется "неточной": 10/3 - и приехали
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354619
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp983 варианта кода, разные результаты
В MSVC2015 одинаковые
Код: plaintext
1.
2.
566546
566546
5665.46
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354623
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИМХУ надо так
Код: plaintext
1.
#define TO_RUB(X) (((X)-floor(X))>0.499?ceil(X):floor(X))  - округляем до целых


т.к. (X)-floor(X) в реале 0.5+-погрешность (10^-15) поэтому надо чуть меньше порог.
Т.к. дискретность два знака после запятой, то 3х знаков достаточно, т.е. 0.499.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354634
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Везёт же некоторым ))
После обеда подумал, что наверное для дефайна промежуточный рез-т вычисляется в длинном буфере.
А вообще, конкретно в этом D'Buildere-2009 отладчик обычно показывает правильное округление, но там скорость не важна. С тех пор как столкнулся с "банковским" округлением RoundTo() и SimpleRoundTo() не отпускал вопрос, почему в библиотеку нельзя было поместить нужную функцию.
2-х шаговое округление девяток тоже не прокатит, потуму как заранее неизвестно, так ли д.б. или это всего лишь погрешность вычислений.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354649
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну обсосано же давно, континуум R отображается на конечное пространство, в к-ром и происходят вычисления, а ещё 5 и 2 взаимно простые.
Не только Изопропилбеда в том что не всякое вещественное число(десятичная дробь в частности) может быть представлено в IEEE 754, но и в соотношении операндов.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354705
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98, проверка на 0.499 чем не понравилась? 19934637

ИМХУ надо именно так проверять, т.к. даже если в данном примере MSVC не дал ошибки, то это не значит что ее никогда не случится на других значениях.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354715
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Потому что хвост вытащил - нос увяз((
потому как заранее неизвестно, точное ли оно или с погрешностью вычислений
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354726
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В целом у нас курс примерно на такое
Dima T главное чтобы всегда было однозначно и остальная математика сходилась в рамках документа. К сож, встречаются расхождения, пытаемся лечить по мере обнаружения.

Несмотря на то, что давно ещё РС начинал с ассемблера на х08-х16, вникать снова желания нет. Если кому интересно, то вот фрагменты из отладки:

File1.cpp.25: if(k==1) { //// 1) ответ 5665,45
Код: plaintext
1.
00401358 837D0801         cmp dword ptr [ebp+$08],$01
0040135C 0F8592020000     jnz $004015f4
File1.cpp.26: xx= yy;
Код: plaintext
1.
2.
3.
00401362 8B4DE8           mov ecx,[ebp-$18]
00401365 894DF0           mov [ebp-$10],ecx
00401368 8B4DEC           mov ecx,[ebp-$14]
0040136B 894DF4           mov [ebp-$0c],ecx
File1.cpp.27: nds = TO_KOP( nds + TO_RUB( xx *100.0f) /100.0f);
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
0040136E DD45F0           fld qword ptr [ebp-$10]
00401371 D80D801A4000     fmul dword ptr [$00401a80]
00401377 83C4F8           add esp,-$08
0040137A DD1C24           fstp qword ptr [esp]
0040137D E81C4E0000       call $0040619e
00401382 83C408           add esp,$08
00401385 DD45F0           fld qword ptr [ebp-$10]
00401388 D80D801A4000     fmul dword ptr [$00401a80]
0040138E DEE1             fsubrp st(1)
00401390 D905841A4000     fld dword ptr [$00401a84]
00401396 D9C9             fxch st(1)
00401398 DAE9             fucompp 
0040139A DFE0             fstsw ax
0040139C 9E               sahf 
0040139D 7219             jb $004013b8
0040139F DD45F0           fld qword ptr [ebp-$10]
004013A2 D80D801A4000     fmul dword ptr [$00401a80]
004013A8 83C4F8           add esp,-$08
004013AB DD1C24           fstp qword ptr [esp]
004013AE E8E54D0000       call $00406198
004013B3 83C408           add esp,$08
004013B6 EB17             jmp $004013cf
004013B8 DD45F0           fld qword ptr [ebp-$10]
004013BB D80D801A4000     fmul dword ptr [$00401a80]
004013C1 83C4F8           add esp,-$08
004013C4 DD1C24           fstp qword ptr [esp]
004013C7 E8D24D0000       call $0040619e
004013CC 83C408           add esp,$08
004013CF DB2D881A4000     fld tbyte ptr [$00401a88]
004013D5 DEC9             fmulp st(1)
004013D7 DC45F8           fadd qword ptr [ebp-$08]
004013DA D80D801A4000     fmul dword ptr [$00401a80]
004013E0 DB7DDC           fstp tbyte ptr [ebp-$24]
004013E3 DD45F0           fld qword ptr [ebp-$10]
004013E6 D80D801A4000     fmul dword ptr [$00401a80]
004013EC 83C4F8           add esp,-$08
004013EF DD1C24           fstp qword ptr [esp]
004013F2 E8A74D0000       call $0040619e
004013F7 83C408           add esp,$08
004013FA DD45F0           fld qword ptr [ebp-$10]
004013FD D80D801A4000     fmul dword ptr [$00401a80]
00401403 DEE1             fsubrp st(1)
00401405 D905841A4000     fld dword ptr [$00401a84]
0040140B D9C9             fxch st(1)
0040140D DAE9             fucompp 
0040140F DFE0             fstsw ax
00401411 9E               sahf 
00401412 7219             jb $0040142d
00401414 DD45F0           fld qword ptr [ebp-$10]
00401417 D80D801A4000     fmul dword ptr [$00401a80]
0040141D 83C4F8           add esp,-$08
00401420 DD1C24           fstp qword ptr [esp]
00401423 E8704D0000       call $00406198
00401428 83C408           add esp,$08
0040142B EB17             jmp $00401444
0040142D DD45F0           fld qword ptr [ebp-$10]
00401430 D80D801A4000     fmul dword ptr [$00401a80]
00401436 83C4F8           add esp,-$08
00401439 DD1C24           fstp qword ptr [esp]
0040143C E85D4D0000       call $0040619e
00401441 83C408           add esp,$08
00401444 DB2D881A4000     fld tbyte ptr [$00401a88]
0040144A DEC9             fmulp st(1)
0040144C DC45F8           fadd qword ptr [ebp-$08]
0040144F D80D801A4000     fmul dword ptr [$00401a80]
00401455 83C4F8           add esp,-$08
00401458 DD1C24           fstp qword ptr [esp]
0040145B E83E4D0000       call $0040619e
00401460 83C408           add esp,$08
00401463 DB6DDC           fld tbyte ptr [ebp-$24]
00401466 DEE1             fsubrp st(1)
00401468 D905841A4000     fld dword ptr [$00401a84]
0040146E D9C9             fxch st(1)
00401470 DAE9             fucompp 
00401472 DFE0             fstsw ax
00401474 9E               sahf 
00401475 0F8285000000     jb $00401500
0040147B DD45F0           fld qword ptr [ebp-$10]
0040147E D80D801A4000     fmul dword ptr [$00401a80]
00401484 83C4F8           add esp,-$08
00401487 DD1C24           fstp qword ptr [esp]
0040148A E80F4D0000       call $0040619e
0040148F 83C408           add esp,$08
00401492 DD45F0           fld qword ptr [ebp-$10]
00401495 D80D801A4000     fmul dword ptr [$00401a80]
0040149B DEE1             fsubrp st(1)
0040149D D905841A4000     fld dword ptr [$00401a84]
004014A3 D9C9             fxch st(1)
004014A5 DAE9             fucompp 
004014A7 DFE0             fstsw ax
004014A9 9E               sahf 
004014AA 7219             jb $004014c5
004014AC DD45F0           fld qword ptr [ebp-$10]
004014AF D80D801A4000     fmul dword ptr [$00401a80]
004014B5 83C4F8           add esp,-$08
004014B8 DD1C24           fstp qword ptr [esp]
004014BB E8D84C0000       call $00406198
004014C0 83C408           add esp,$08
004014C3 EB17             jmp $004014dc
004014C5 DD45F0           fld qword ptr [ebp-$10]
004014C8 D80D801A4000     fmul dword ptr [$00401a80]
004014CE 83C4F8           add esp,-$08
004014D1 DD1C24           fstp qword ptr [esp]
004014D4 E8C54C0000       call $0040619e
004014D9 83C408           add esp,$08
004014DC DB2D881A4000     fld tbyte ptr [$00401a88]
004014E2 DEC9             fmulp st(1)
004014E4 DC45F8           fadd qword ptr [ebp-$08]
004014E7 D80D801A4000     fmul dword ptr [$00401a80]
004014ED 83C4F8           add esp,-$08
004014F0 DD1C24           fstp qword ptr [esp]
004014F3 E8A04C0000       call $00406198
004014F8 83C408           add esp,$08
004014FB E980000000       jmp $00401580
00401500 DD45F0           fld qword ptr [ebp-$10]
00401503 D80D801A4000     fmul dword ptr [$00401a80]
00401509 83C4F8           add esp,-$08
0040150C DD1C24           fstp qword ptr [esp]
0040150F E88A4C0000       call $0040619e
00401514 83C408           add esp,$08
00401517 DD45F0           fld qword ptr [ebp-$10]
0040151A D80D801A4000     fmul dword ptr [$00401a80]
00401520 DEE1             fsubrp st(1)
00401522 D905841A4000     fld dword ptr [$00401a84]
00401528 D9C9             fxch st(1)
0040152A DAE9             fucompp 
0040152C DFE0             fstsw ax
0040152E 9E               sahf 
0040152F 7219             jb $0040154a
00401531 DD45F0           fld qword ptr [ebp-$10]
00401534 D80D801A4000     fmul dword ptr [$00401a80]
0040153A 83C4F8           add esp,-$08
0040153D DD1C24           fstp qword ptr [esp]
00401540 E8534C0000       call $00406198
00401545 83C408           add esp,$08
00401548 EB17             jmp $00401561
0040154A DD45F0           fld qword ptr [ebp-$10]
0040154D D80D801A4000     fmul dword ptr [$00401a80]
00401553 83C4F8           add esp,-$08
00401556 DD1C24           fstp qword ptr [esp]
00401559 E8404C0000       call $0040619e
0040155E 83C408           add esp,$08
00401561 DB2D881A4000     fld tbyte ptr [$00401a88]
00401567 DEC9             fmulp st(1)
00401569 DC45F8           fadd qword ptr [ebp-$08]
0040156C D80D801A4000     fmul dword ptr [$00401a80]
00401572 83C4F8           add esp,-$08
00401575 DD1C24           fstp qword ptr [esp]
00401578 E8214C0000       call $0040619e
0040157D 83C408           add esp,$08
00401580 DB2D881A4000     fld tbyte ptr [$00401a88]
00401586 DEC9             fmulp st(1)
00401588 DD5DF8           fstp qword ptr [ebp-$08]
File1.cpp.28: nds= TO_RUB( xx*100.0f );
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
0040158B DD45F0           fld qword ptr [ebp-$10]
0040158E D80D801A4000     fmul dword ptr [$00401a80]
00401594 83C4F8           add esp,-$08
00401597 DD1C24           fstp qword ptr [esp]
0040159A E8FF4B0000       call $0040619e
0040159F 83C408           add esp,$08
004015A2 DD45F0           fld qword ptr [ebp-$10]
004015A5 D80D801A4000     fmul dword ptr [$00401a80]
004015AB DEE1             fsubrp st(1)
004015AD D905841A4000     fld dword ptr [$00401a84]
004015B3 D9C9             fxch st(1)
004015B5 DAE9             fucompp 
004015B7 DFE0             fstsw ax
004015B9 9E               sahf 
004015BA 7219             jb $004015d5
004015BC DD45F0           fld qword ptr [ebp-$10]
004015BF D80D801A4000     fmul dword ptr [$00401a80]
004015C5 83C4F8           add esp,-$08
004015C8 DD1C24           fstp qword ptr [esp]
004015CB E8C84B0000       call $00406198
004015D0 83C408           add esp,$08
004015D3 EB17             jmp $004015ec
004015D5 DD45F0           fld qword ptr [ebp-$10]
004015D8 D80D801A4000     fmul dword ptr [$00401a80]
004015DE 83C4F8           add esp,-$08
004015E1 DD1C24           fstp qword ptr [esp]
004015E4 E8B54B0000       call $0040619e
004015E9 83C408           add esp,$08
004015EC DD5DF8           fstp qword ptr [ebp-$08]
File1.cpp.29: } else if (k==2) { //// 2) ответ 5665,46
Код: plaintext
1.
2.
3.
004015EF E985040000       jmp $00401a79
004015F4 837D0802         cmp dword ptr [ebp+$08],$02
004015F8 0F85DC010000     jnz $004017da
File1.cpp.30: xx= yy *100.0f;
Код: plaintext
1.
2.
3.
004015FE DD45E8           fld qword ptr [ebp-$18]
00401601 D80D801A4000     fmul dword ptr [$00401a80]
00401607 DD5DF0           fstp qword ptr [ebp-$10]
File1.cpp.31: nds = TO_KOP( nds + TO_RUB( xx ) /100.0f);
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
0040160A FF75F4           push dword ptr [ebp-$0c]
0040160D FF75F0           push dword ptr [ebp-$10]
00401610 E8894B0000       call $0040619e
00401615 83C408           add esp,$08
00401618 DC6DF0           fsubr qword ptr [ebp-$10]
0040161B D905841A4000     fld dword ptr [$00401a84]
00401621 D9C9             fxch st(1)
00401623 DAE9             fucompp 
00401625 DFE0             fstsw ax
00401627 9E               sahf 
00401628 7210             jb $0040163a
0040162A FF75F4           push dword ptr [ebp-$0c]
0040162D FF75F0           push dword ptr [ebp-$10]
00401630 E8634B0000       call $00406198
00401635 83C408           add esp,$08
00401638 EB0E             jmp $00401648
0040163A FF75F4           push dword ptr [ebp-$0c]
0040163D FF75F0           push dword ptr [ebp-$10]
00401640 E8594B0000       call $0040619e
00401645 83C408           add esp,$08
00401648 DB2D881A4000     fld tbyte ptr [$00401a88]
0040164E DEC9             fmulp st(1)
00401650 DC45F8           fadd qword ptr [ebp-$08]
00401653 D80D801A4000     fmul dword ptr [$00401a80]
00401659 DB7DD0           fstp tbyte ptr [ebp-$30]
0040165C FF75F4           push dword ptr [ebp-$0c]
0040165F FF75F0           push dword ptr [ebp-$10]
00401662 E8374B0000       call $0040619e
00401667 83C408           add esp,$08
0040166A DC6DF0           fsubr qword ptr [ebp-$10]
0040166D D905841A4000     fld dword ptr [$00401a84]
00401673 D9C9             fxch st(1)
00401675 DAE9             fucompp 
00401677 DFE0             fstsw ax
00401679 9E               sahf 
0040167A 7210             jb $0040168c
0040167C FF75F4           push dword ptr [ebp-$0c]
0040167F FF75F0           push dword ptr [ebp-$10]
00401682 E8114B0000       call $00406198
00401687 83C408           add esp,$08
0040168A EB0E             jmp $0040169a
0040168C FF75F4           push dword ptr [ebp-$0c]
0040168F FF75F0           push dword ptr [ebp-$10]
00401692 E8074B0000       call $0040619e
00401697 83C408           add esp,$08
0040169A DB2D881A4000     fld tbyte ptr [$00401a88]
004016A0 DEC9             fmulp st(1)
004016A2 DC45F8           fadd qword ptr [ebp-$08]
004016A5 D80D801A4000     fmul dword ptr [$00401a80]
004016AB 83C4F8           add esp,-$08
004016AE DD1C24           fstp qword ptr [esp]
004016B1 E8E84A0000       call $0040619e
004016B6 83C408           add esp,$08
004016B9 DB6DD0           fld tbyte ptr [ebp-$30]
004016BC DEE1             fsubrp st(1)
004016BE D905841A4000     fld dword ptr [$00401a84]
004016C4 D9C9             fxch st(1)
004016C6 DAE9             fucompp 
004016C8 DFE0             fstsw ax
004016CA 9E               sahf 
004016CB 725F             jb $0040172c
004016CD FF75F4           push dword ptr [ebp-$0c]
004016D0 FF75F0           push dword ptr [ebp-$10]
004016D3 E8C64A0000       call $0040619e
004016D8 83C408           add esp,$08
004016DB DC6DF0           fsubr qword ptr [ebp-$10]
004016DE D905841A4000     fld dword ptr [$00401a84]
004016E4 D9C9             fxch st(1)
004016E6 DAE9             fucompp 
004016E8 DFE0             fstsw ax
004016EA 9E               sahf 
004016EB 7210             jb $004016fd
004016ED FF75F4           push dword ptr [ebp-$0c]
004016F0 FF75F0           push dword ptr [ebp-$10]
004016F3 E8A04A0000       call $00406198
004016F8 83C408           add esp,$08
004016FB EB0E             jmp $0040170b
004016FD FF75F4           push dword ptr [ebp-$0c]
00401700 FF75F0           push dword ptr [ebp-$10]
00401703 E8964A0000       call $0040619e
00401708 83C408           add esp,$08
0040170B DB2D881A4000     fld tbyte ptr [$00401a88]
00401711 DEC9             fmulp st(1)
00401713 DC45F8           fadd qword ptr [ebp-$08]
00401716 D80D801A4000     fmul dword ptr [$00401a80]
0040171C 83C4F8           add esp,-$08
0040171F DD1C24           fstp qword ptr [esp]
00401722 E8714A0000       call $00406198
00401727 83C408           add esp,$08
0040172A EB5D             jmp $00401789
0040172C FF75F4           push dword ptr [ebp-$0c]
0040172F FF75F0           push dword ptr [ebp-$10]
00401732 E8674A0000       call $0040619e
00401737 83C408           add esp,$08
0040173A DC6DF0           fsubr qword ptr [ebp-$10]
0040173D D905841A4000     fld dword ptr [$00401a84]
00401743 D9C9             fxch st(1)
00401745 DAE9             fucompp 
00401747 DFE0             fstsw ax
00401749 9E               sahf 
0040174A 7210             jb $0040175c
0040174C FF75F4           push dword ptr [ebp-$0c]
0040174F FF75F0           push dword ptr [ebp-$10]
00401752 E8414A0000       call $00406198
00401757 83C408           add esp,$08
0040175A EB0E             jmp $0040176a
0040175C FF75F4           push dword ptr [ebp-$0c]
0040175F FF75F0           push dword ptr [ebp-$10]
00401762 E8374A0000       call $0040619e
00401767 83C408           add esp,$08
0040176A DB2D881A4000     fld tbyte ptr [$00401a88]
00401770 DEC9             fmulp st(1)
00401772 DC45F8           fadd qword ptr [ebp-$08]
00401775 D80D801A4000     fmul dword ptr [$00401a80]
0040177B 83C4F8           add esp,-$08
0040177E DD1C24           fstp qword ptr [esp]
00401781 E8184A0000       call $0040619e
00401786 83C408           add esp,$08
00401789 DB2D881A4000     fld tbyte ptr [$00401a88]
0040178F DEC9             fmulp st(1)
00401791 DD5DF8           fstp qword ptr [ebp-$08]
File1.cpp.32: nds= TO_RUB( xx );
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
00401794 FF75F4           push dword ptr [ebp-$0c]
00401797 FF75F0           push dword ptr [ebp-$10]
0040179A E8FF490000       call $0040619e
0040179F 83C408           add esp,$08
004017A2 DC6DF0           fsubr qword ptr [ebp-$10]
004017A5 D905841A4000     fld dword ptr [$00401a84]
004017AB D9C9             fxch st(1)
004017AD DAE9             fucompp 
004017AF DFE0             fstsw ax
004017B1 9E               sahf 
004017B2 7210             jb $004017c4
004017B4 FF75F4           push dword ptr [ebp-$0c]
004017B7 FF75F0           push dword ptr [ebp-$10]
004017BA E8D9490000       call $00406198
004017BF 83C408           add esp,$08
004017C2 EB0E             jmp $004017d2
004017C4 FF75F4           push dword ptr [ebp-$0c]
004017C7 FF75F0           push dword ptr [ebp-$10]
004017CA E8CF490000       call $0040619e
004017CF 83C408           add esp,$08
004017D2 DD5DF8           fstp qword ptr [ebp-$08]
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354778
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98Потому что хвост вытащил - нос увяз((
потому как заранее неизвестно, точное ли оно или с погрешностью вычислений
А ты посчитай. У double матрисса 52 бита (точнее почти 53) 2^52 ~=10^15, т.е. первые 15 десятичных разрядов будут представлены точно и плюс хвостик погрешности, т.е. погрешность вылезет на 16-м разряде.
Если у тебя рубли в копейками, то максимум 10 000 000 000 000.00 можно точно представить.
Используем один разряд для разграничения, остается 1 000 000 000 000.00. До этой суммы можешь не переживать за погрешности.
Но погрешность надо учитывать, т.к. она в обе стороны может исказить точное значение, поэтому 0.5 надо представлять как 0.50 - 0.001, т.е. 0.499
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354852
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилMasterZivнет, арифметика тоже неточная.
что значит "неточная"?
десятичная - тож окажется "неточной": 10/3 - и приехали


10/3 - не десятичная дробь.

арифметика с плач. точкой неточная, потому что представление чисел уже неточно, все числа изображаются в виде чисел, ....


блин, да лень писать, неточная арифметика с плавающей точкой, и все. хочешь доказательств - найди сам в сети.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39354872
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv,

спорить бесполезно - называйте неточной
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355151
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98,

в mingw одинаковые результаты
автор5665.455 = 5665.45499999999992724042
5665.45 = 5665.44999999999981810106
5665.46 = 5665.46000000000003637979

1 = 566546.00000000000000000000
2 = 566546.00000000000000000000
3 = 5665.46000000000003637979
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
#define TO_RUB(A) (((A)-floor(A))>=0.5?ceil(A):floor(A))
#define TO_KOP(A) (TO_RUB((A)*100.0f)/100.0f)

double NDS (int k);

using namespace std;

//-------------------------------------------------------

int main()
{
    printf("5665.455 = %20.20f\n", 5665.455);
    printf("5665.45  = %20.20f\n", 5665.45);
    printf("5665.46  = %20.20f\n", 5665.46);
    printf("\n");

    NDS(0);

    return 0;
}
//-------------------------------------------------------

double NDS ( int k)
{
        double nds = 0.0;
        double xx, yy= 5665.455;

        {  //// 1) ответ 5665,45
            xx= yy;
            nds = TO_KOP( nds + TO_RUB( xx *100.0f) /100.0f);
            nds= TO_RUB( xx*100.0f );

            printf("1 = %20.20f\n", nds);
        }

        {  //// 2) ответ 5665,46
            xx= yy *100.0f;
            nds = TO_KOP( nds + TO_RUB( xx ) /100.0f);
            nds= TO_RUB( xx );

            printf("2 = %20.20f\n", nds);
        }

        {  //// 3)   ответ 5665,45
            xx= yy;
            nds = TO_KOP( nds + TO_KOP( xx ));
            nds= TO_KOP( xx );

            printf("3 = %20.20f\n", nds);
        }//end_if
    return nds;
}

только числа 5665.45 и 5665.46 в любом случае в double получаются приближенными, имхо округлять до 0,01 их бесполезно
и выкинь в округлении floor и ceil, возможно у билдера в них ошибки, замени на
Код: plaintext
1.
2.
double TO_RUB(double A) { return (int)( A + 0.5 ); }
double TO_KOP(double A) { return (int)( A*100.0 + 0.5)/100.0; }
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355597
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98, может для денежных расчётов использовать рациональные числа? Ведь арифметические операции с ними делаются без погрешности. Например, есть библиотека GMP :
GMP function categories
...
2. High-level rational arithmetic functions (mpq). This category consists of about 35 functions, but all mpz functions can be used too, by applying them to the numerator and denominator separately.
...
4. C++ class based interface to all of the above. (The C functions and types can of course be used directly from C++ too.)

Изопропилспорить бесполезно - называйте неточнойFloating point арифметика -- детерминированная (без random-а), но неточная:
Код: plaintext
1.
2.
double x = 10000000000000000.0;
assert(x + 1.0 == x);
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355617
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр СедовFloating point арифметика -- детерминированная (без random-а), но неточная
что характерно - арифметика с фиксированной точкой обладает этими же свойствами
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355659
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилПётр СедовFloating point арифметика -- детерминированная (без random-а), но неточная
что характерно - арифметика с фиксированной точкой обладает этими же свойствамиПоэтому fixed point арифметику тоже лучше не использовать для денежных расчётов. А вот рациональная арифметика -- она без погрешности, например с помощью библиотеки GMP:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <stdio.h>
#include "gmpxx.h"

int main() {
  mpq_class a("3/10", /*base:*/10); // в точности 0.3
  mpq_class b("1/10", /*base:*/10); // в точности 0.1
  mpq_class c = a + b;
  printf("c = %s\n", c.get_str().c_str());

  mpq_class x("10000000000000000", /*base:*/10);
  mpq_class y("1", /*base:*/10);
  mpq_class z = x + y;
  printf("z = %s\n", z.get_str().c_str());

  return 0;
}

Вывод на консоль:
Код: sql
1.
2.
c = 2/5
z = 10000000000000001

Но это конечно медленнее работает, чем с double-ами.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355744
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Телушка - полушка, да рубль перевоз. ТЗ такое было изначально, позволяющее вольности. Кабы с нуля всё строить, а тут тогда всё перелопачивать. Да и инткрфейс тоже тогда будет (уже) тормозить, ну то есть всю концепцию заново тогда во всх проектах и процы в базе тоже. И ради чего? чтоб в договоре и связанных с ним документах всегда было тип-топ.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355763
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T1 000 000 000 000.00. До этой суммы можешь не переживать за погрешности.
Ты забываешь, что 15 знаков вмсте с дробью, т.е. вылезет и на 123456.7499999988. Просто чем точнее отсекать (0.000001), тем меньше будет вероятность ошибок 1-го и 2-го рода - я об этом сейчас думаю. Всё равно неск. раз в году происходит. Только сейчас первый случай, в к-ром билдер замечен, а причина до сих пор непонятна.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355771
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98Dima T1 000 000 000 000.00. До этой суммы можешь не переживать за погрешности.
Ты забываешь, что 15 знаков вмсте с дробью, т.е. вылезет и на 123456.7499999988. Просто чем точнее отсекать (0.000001), тем меньше будет вероятность ошибок 1-го и 2-го рода - я об этом сейчас думаю. Всё равно неск. раз в году происходит. Только сейчас первый случай, в к-ром билдер замечен, а причина до сих пор непонятна.
Я не забываю. То что после третьего знака после запятой - неважно. Зачем тебе точнее если ты в копейках учет ведешь? Т.е. считаешь без округлений и в конце округляешь.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355839
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну да, слагаемые должны быть большей точности, чем сумма. Но в данной ветке числа не вычисляются, а много раз складываются готовые НДС из БД, в данном случае ~7-8 раз в двойном цикле. И предполагается, что их сумма и каждый промежуточный рез-т в конце сойдётся с итогом НДС. А числа гадкие, и на экране сразу видно навроде
ИТОГО=ххх,00
НДС= уу,99
ВСЕГО с НДС= zzz,00

Операция round(a+b+c+d ) не дистрибутивна относительно суммы, и для суммы НДС округлять нужно бы каждое слагаемое. Ну это как "немного изменить последнюю цифру телефонного номера".
При том ведь ошибка вылезла на другом значении, потому что слагаемые не округлялись - я не долго думая округлил, решил посмотреть как скажется в других случаях, ткнул в случайное место - а тут такая фигня. Ну то есть хвост вытащил - нос увяз.

Всегда сконялся к варианту двойного преобразования по типу:
(double)( (__int64) (aa+0.5) + bb ) , но любая правка кроме подмены макроса - это в сотнях мест, и опять поедут старые значения, а вообще тысяча мест, где подобные сложения. Ну неподъёмно это, поэтому я так консервативен в ответах .
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355844
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m_Sladouble TO_RUB(double A) { return (int)( A + 0.5 ); }Наверное это лучший вариант.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355860
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98m_Sladouble TO_RUB(double A) { return (int)( A + 0.5 ); }Наверное это лучший вариант.
Ну и чем он лучший? Разве что побыстрее твоего отработает. Это математическое округление через округление вниз. 1.234999999999999999 округлится до 1.23.
Проблемы с точностью тут абсолютно те же что и твоем первом посте.

Ты пойми, погрешность она в обе стороны бывает: и в плюс и в минус. У тебя все проблемы в том что в минус ты не учитываешь.
В данном случае надо A + 0.5 1
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355864
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98Ну да, слагаемые должны быть большей точности, чем сумма. Но в данной ветке числа не вычисляются, а много раз складываются готовые НДС из БД, в данном случае ~7-8 раз в двойном цикле. И предполагается, что их сумма и каждый промежуточный рез-т в конце сойдётся с итогом НДС. А числа гадкие, и на экране сразу видно навроде
ИТОГО=ххх,00
НДС= уу,99
ВСЕГО с НДС= zzz,00
Если готовые, посчитанные с точностью до копейки, т.е. округленные до копеек при сохранении, то в худшем случае погрешность будет 8/2^53 = 8.8*10^-16, т.е. гарантированно 15 первых знаков точно будут вычислены, дальше надо просто округлить результат до копеек, чтобы окончательно убрать накопленную погрешность.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355937
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima_T, да, он быстрее в работе и для исправления. В БД всякие значения, рассчитанные в разное время в прошлом: с ошибками и без, с округлениями и без, исправленные и нет. Для некоторых денег это неважно, для других важно, но не фатально.

Повторюсь exp98об этом я в курсе ещё с больших машин ....
Переделывать тогда уж сотню файлов и процы в БД, да и саму БД переводить на копейки. Это не вариант.
Вопрос в том, почему дефайн считает не как я думаю, ну или наоборот.Последнее изначально было единственной целью вопроса.

Ну вот ответь мне, какое множество ошибок ты предлагаешь упорядочить 1-го рода, 2-го рода? или некую их взвеш. сумму и тогда в каком соотношении? ну чтоб хотя бы численно ргументировать ...
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39355976
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98Ну вот ответь мне, какое множество ошибок ты предлагаешь упорядочить 1-го рода, 2-го рода? или некую их взвеш. сумму и тогда в каком соотношении? ну чтоб хотя бы численно ргументировать ...
Что такое "род" я не понял.

Суть в следующем: на вход должны поступать значения с минимальной погрешностью, в твоем случае округленные до копеек, затем производиться вычислительные операции и по окончанию результат округляться до копеек.

Если вход заведомо округлен (или округлить принудительно), то можно рассчитывать максимальную накопленную погрешность. Исходная погрешность составляет плюс-минус X*1/2^53, где X точное значение. Потому что дискретность мантиссы 1/2^52 и при преобразовании из десятичного приводится к наиболее близкому большему или меньшему, т.е. погрешность это плюс-минус половина дискретности.
Дальше просто: делаем предположение что все входные данные это наихудший случай, например надо сложить 8 одинаковых значений с максимальной погрешностью, т.е. погрешность суммы будет 8*X*1/2^53 = X*8.8*10^-16.
Теперь ищем максимальный результат, в котором будет искажение более чем на 0.005, т.е. округление до копеек даст ошибку.
0.005 / 8.8*10^-16 = 5 681 818 181 818,18
Если у тебя результаты не превышают 5 681 818 181 818,18 то результат сложения 8 значений будет гарантированно точный.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39356009
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По поводу округления (понял как точно посчитать), если смещаем на 0,01 копейки (+0.0051), чтобы отрицательные погрешности учесть, то можно смело так округлять числа до
Код: plaintext
0.0001 / 2^53 = 900 719 925 474,10
или почти 15 десятичных знаков.

С математикой округления можно еще пооптимизировать, сходу не соображу до скольки можно добавить, вроде 0.0004 (+0.0054) должно тоже точно работать и увеличит макс. значение до 3 602 879 701 896,40 или 15 десятичных знаков. Подзабыл математику :(
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39356024
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это из статистики о принятии и отпрасывании гипотез.
В одном случае мы (ошибочно) принимаем некоторые события за истинные. В другом случае (ошибочно) отбрасываем истинные события.

У нас есть двоичное число. Используем его в плавающем формате для сравнения. В проге при сравнении мы отождествляем все числа, отличающиеся от некоторого на маленькую дельту. При этом некоторые числа справедливо будут отождествлены, а некоторые - в рез-те погрешностей вычислений.
То есть часть чисел будет представлено округлённым справедливо, а часть нет, но нам приходится принимать это как есть. Гипотеза (о справедливости округления) содержит ошибки "одного рода".

Остальные числа не пройдут сравнение и не будут округлены аналогично. Соответственно парная первой ггипотеза о ненужности округления этих чисел содержит ошибку "другого рода".

Ну и вопрос мой был каких ошибок больше и на сколько: справедливо округлённых или несправедливо неокруглённых, примерно так.

А вообще мне сейчас с базой и VS надо копаться, вникать в ответы позднее буду.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39387910
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нконец вернулся к этому вопросу. Вот ты писал
Dima Tесли смещаем на 0,01 копейки (+0.0051) .... до скольки можно добавить, вроде 0.0004 (+0.0054) должно тоже точно работать ... В целом правильные рассуждения, только ошибок принятия решиний всё равно не избежать. Я сегодня смотрел на вполне безобидных числах.
Например получил я в расчёте с ТОЧНЫМИ числами, нечто, что выглядит как yy= 5665.4549
Пусть именно оно и есть НДС.

Если использовать логику окруления +-0.0051 руб, то НДС= 5665.45,
если +-0.0052, то НДС= 5665.46

Например, (уу*100.0)*0.01 = 5665.454899999999

А как д.б. знает только калькулятор или же спецалгоритмы .... только ГУИ тормозить будет при обсчёте и смене массива данных. И использовать это только для денег. Сейчас TO_RUB() используется иногда и для обчной целой части.

И легко напридумать похожих чисел для порогов вида 0.0050001 руб и т.п.
Я смотрел в варианте, т.к. это самая простая правка
Код: plaintext
1.
2.
3.
4.
5.
#define MY_EPSILON_0_5  0.51
double TO_KOP(double A) { return (__int64)( A*100.0 + MY_EPSILON_0_5) *0.01; }

nds= TO_KOP( yy);
printf("%20.20f\n", nds);


Моё резюме таково же как выше все и пишут, double - не самый лучший формат для денежных операций.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39387925
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exp98, недавно похожая тема была 20077393 , подходит double для денег, но пользоваться им надо аккуратно.

Что касается НДС, то там где деление (умножение на нецелое), точность в принципе теряется.
Сумма НДС 18%Сумма с НДС1.240.221.461.240.221.461.240.221.46

Итого по столбцам
Сумма НДС 18%Сумма с НДС3.720.664.36
Но 18% от 3.72 это 0.67 будет.
...
Рейтинг: 0 / 0
и снова копейки: #define, С++ , Builder 2009 ?
    #39388386
exp98
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну разумеется аккуратно. Я за себя говорю, в моём случае тогда придётся затормозить ГУИ или же частично переделать фреймворк в денежной части под эффективные алгоритмы, возможно с правками процедур в БД. А параллельно с этим продолжать доработки на прежней схеме. Не до такой же степени я трудоголик. И всем спасибо за варианты и ссылки.
...
Рейтинг: 0 / 0
46 сообщений из 46, показаны все 2 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / и снова копейки: #define, С++ , Builder 2009 ?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]