Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Проблемка округления в дебилдере 2009. Не отвлекаемся на теорию прибл-х вычислений вообще и в компах в частности. Интересует, влияет ли #define , или конкретно 2009-й дебилдер, или особенности проги, в сочетании с хитрым вычисляемым числом? Ниже я намеренно привожу чуть больший контекст. Есть описания: Код: plaintext 1. 2. 3. Есть 2 варианта кода: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Вопрос в том, почему в рантайм и в отладке Код: plaintext 1. 2. Это видно по итоговому результату nds в пользовательском окне - там тоже округление, но уже в текстовый вид. Казалось бы эквивалентно, но нет, а почему? П.С. Ну да, в битовом виде на лету промежуточный рез-т "5665.455" не смотрел. Ну а само оно = 5665.4549999...9986... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.11.2016, 17:13 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Похоже дибилдер из вас двоих не компилятор.. Компилятор все правильно тебе говорит. Ненужно округлять посреди расчетов. Округление только конечного результата. при представлении для человека. Вообще тип money - 4 знака после запятой ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.11.2016, 18:26 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98П.С. Ну да, в битовом виде на лету промежуточный рез-т "5665.455" не смотрел. Ну а само оно = 5665.4549999...9986... после расчетов может оказаться 5665.4550000...0011... и тоже будет правильно. Сравнивай не с 0.5, а с 0.5000000001 или 0.4999999999 не соображу сходу как правильно. А в целом пофиг как округлится при расчете НДС, главное чтобы всегда было однозначно и остальная математика сходилась в рамках документа. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.11.2016, 18:40 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
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... Потому что даже когда ты в отладчике видишь число, оно уже может быть представлено с погрешностью. Плавающая арифметика в принципе неточная. Она даже внутри в машине, в регистрах, уже неточно может храниться. Бессмысленно что-то проверять на "такой/не такой". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 01:33 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98, пробуй так округлять Код: plaintext 1. 2. и дай полный исходник теста, попробую посмотреть как mingw себя ведет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 05:45 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
MasterZiv, знаю твоё неравнодушие к округлениям, об этом я в курсе ещё с больших машин, когда обрабатывал СПРН. Переделывать тогда уж сотню файлов и процы в БД, да и саму БД переводить на копейки. Это не вариант. Вопрос в том, почему дефайн считает не как я думаю, ну или наоборот. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 09:40 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
locked, уважаемый, складывать надо в копейках, а не в грошах, иначе столкнётесь с вопросом, почему округлённая сумма не равна сумме округлений. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 09:42 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Dima TСравнивай не с 0.5, а с 0.5000000001 или 0.4999999999 не соображу сходу как правильно.согласен, мысль здравая. Это уже я сам 0.5 написал. Только вопрос возник, когда сравнение ещё стояло: X-floor(X) >= ceil(X)-X И вот хоть убей, в дефайне даёт одно, а при разбивке на этапы другое. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 09:49 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
m_Sla и дай полный исходник теста, попробую посмотреть как mingw себя ведет Совсем полный исходник сложно, т.к. вместо моего funct() стоит что-то вроде A->B->at(i)->nds, всё это в цикле, где последнее nds - на самом деле свойство совсем другого класса, и там тоже суммирование, и оно тоже дёргает функцию, к-рая лезет в БД. Попробую слепить отдельно стоящий фрагмент. И конечно же, моё 5665,455 - это не всамоделишнее число, а как мне его кажет отладчик. О! сначала попробую перед прогоном это число руками влепить и посмотрю. Так что попозднее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 10:00 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
И кстати, если кого коробит моё "дебилдер" - это не от того, что сейчас вопрос про округления, и не от того, что вместо функции математического округления он использует т.н. "банковское" округление. Это относится конкретно к пользуемой мною версии 2009, т.к. его редактор! исходников не только не справляется с русскоязычными коментами, но и часто не различает положение курсора в тексте и в своих думах, а также часто и не предсказуемо зависет, а то и попросту курочит исходники, превращая их в нечто бинарное. Но что есть, то есть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 10:14 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
MasterZivПлавающая арифметика в принципе неточная арифметика сама по себе точная и в регистрах значения "точные", беда в том что не всякое вещественное число(десятичная дробь в частности) может быть представлено в IEEE 754 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 11:10 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98И кстати, если кого коробит моё "дебилдер"2009й действительно совсем кривой был. Либо 2007, либо 2010 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 11:11 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
ИзопропилMasterZivПлавающая арифметика в принципе неточная арифметика сама по себе точная и в регистрах значения "точные", беда в том что не всякое вещественное число(десятичная дробь в частности) может быть представлено в IEEE 754 нет, арифметика тоже неточная. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 11:47 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98MasterZiv, знаю твоё неравнодушие к округлениям, об этом я в курсе ещё с больших машин, когда обрабатывал СПРН. Переделывать тогда уж сотню файлов и процы в БД, да и саму БД переводить на копейки. Это не вариант. ты можешь хоть всю жизнь идти к северному полюсу по магнитному компасу, но все равно не дойдешь... exp98Вопрос в том, почему дефайн считает не как я думаю, ну или наоборот. не глядел твои макросы , если не устраивает, используй функции, в чем проблема? шаблонные, если надо. они отлаживаются. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 11:54 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98, чтобы понять, что там у тебя, нужен полный код. полный , рабочий код. нужно знать типы данных всех переменных и то, как ты их выводишь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 11:58 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
MasterZiv, все они double, и методы возвращают double, проверено неоднократно. Когда-то оставались float, ош. сразу вылезали при числах больше 7 цифр. Я выберу время на простой пример, и если воспроизведётся, то запостю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 12:20 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 14:03 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
MasterZivнет, арифметика тоже неточная. что значит "неточная"? десятичная - тож окажется "неточной": 10/3 - и приехали ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 14:39 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp983 варианта кода, разные результаты В MSVC2015 одинаковые Код: plaintext 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 14:44 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
ИМХУ надо так Код: plaintext 1. т.к. (X)-floor(X) в реале 0.5+-погрешность (10^-15) поэтому надо чуть меньше порог. Т.к. дискретность два знака после запятой, то 3х знаков достаточно, т.е. 0.499. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 14:55 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Везёт же некоторым )) После обеда подумал, что наверное для дефайна промежуточный рез-т вычисляется в длинном буфере. А вообще, конкретно в этом D'Buildere-2009 отладчик обычно показывает правильное округление, но там скорость не важна. С тех пор как столкнулся с "банковским" округлением RoundTo() и SimpleRoundTo() не отпускал вопрос, почему в библиотеку нельзя было поместить нужную функцию. 2-х шаговое округление девяток тоже не прокатит, потуму как заранее неизвестно, так ли д.б. или это всего лишь погрешность вычислений. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 15:05 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Ну обсосано же давно, континуум R отображается на конечное пространство, в к-ром и происходят вычисления, а ещё 5 и 2 взаимно простые. Не только Изопропилбеда в том что не всякое вещественное число(десятичная дробь в частности) может быть представлено в IEEE 754, но и в соотношении операндов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 15:20 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98, проверка на 0.499 чем не понравилась? 19934637 ИМХУ надо именно так проверять, т.к. даже если в данном примере MSVC не дал ошибки, то это не значит что ее никогда не случится на других значениях. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 16:34 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Потому что хвост вытащил - нос увяз(( потому как заранее неизвестно, точное ли оно или с погрешностью вычислений ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 16:42 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
В целом у нас курс примерно на такое Dima T главное чтобы всегда было однозначно и остальная математика сходилась в рамках документа. К сож, встречаются расхождения, пытаемся лечить по мере обнаружения. Несмотря на то, что давно ещё РС начинал с ассемблера на х08-х16, вникать снова желания нет. Если кому интересно, то вот фрагменты из отладки: File1.cpp.25: if(k==1) { //// 1) ответ 5665,45 Код: plaintext 1. Код: plaintext 1. 2. 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. 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. Код: 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. Код: plaintext 1. 2. 3. Код: plaintext 1. 2. 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. 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. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 17:07 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
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 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 18:20 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
ИзопропилMasterZivнет, арифметика тоже неточная. что значит "неточная"? десятичная - тож окажется "неточной": 10/3 - и приехали 10/3 - не десятичная дробь. арифметика с плач. точкой неточная, потому что представление чисел уже неточно, все числа изображаются в виде чисел, .... блин, да лень писать, неточная арифметика с плавающей точкой, и все. хочешь доказательств - найди сам в сети. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 20:27 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
MasterZiv, спорить бесполезно - называйте неточной ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.11.2016, 22:00 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
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. и выкинь в округлении floor и ceil, возможно у билдера в них ошибки, замени на Код: plaintext 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.11.2016, 20:05 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
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. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.11.2016, 23:36 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Пётр СедовFloating point арифметика -- детерминированная (без random-а), но неточная что характерно - арифметика с фиксированной точкой обладает этими же свойствами ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 00:31 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
ИзопропилПётр СедовFloating point арифметика -- детерминированная (без random-а), но неточная что характерно - арифметика с фиксированной точкой обладает этими же свойствамиПоэтому fixed point арифметику тоже лучше не использовать для денежных расчётов. А вот рациональная арифметика -- она без погрешности, например с помощью библиотеки GMP: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Вывод на консоль: Код: sql 1. 2. Но это конечно медленнее работает, чем с double-ами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 04:09 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Телушка - полушка, да рубль перевоз. ТЗ такое было изначально, позволяющее вольности. Кабы с нуля всё строить, а тут тогда всё перелопачивать. Да и инткрфейс тоже тогда будет (уже) тормозить, ну то есть всю концепцию заново тогда во всх проектах и процы в базе тоже. И ради чего? чтоб в договоре и связанных с ним документах всегда было тип-топ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 10:14 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Dima T1 000 000 000 000.00. До этой суммы можешь не переживать за погрешности. Ты забываешь, что 15 знаков вмсте с дробью, т.е. вылезет и на 123456.7499999988. Просто чем точнее отсекать (0.000001), тем меньше будет вероятность ошибок 1-го и 2-го рода - я об этом сейчас думаю. Всё равно неск. раз в году происходит. Только сейчас первый случай, в к-ром билдер замечен, а причина до сих пор непонятна. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 10:31 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98Dima T1 000 000 000 000.00. До этой суммы можешь не переживать за погрешности. Ты забываешь, что 15 знаков вмсте с дробью, т.е. вылезет и на 123456.7499999988. Просто чем точнее отсекать (0.000001), тем меньше будет вероятность ошибок 1-го и 2-го рода - я об этом сейчас думаю. Всё равно неск. раз в году происходит. Только сейчас первый случай, в к-ром билдер замечен, а причина до сих пор непонятна. Я не забываю. То что после третьего знака после запятой - неважно. Зачем тебе точнее если ты в копейках учет ведешь? Т.е. считаешь без округлений и в конце округляешь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 10:40 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Ну да, слагаемые должны быть большей точности, чем сумма. Но в данной ветке числа не вычисляются, а много раз складываются готовые НДС из БД, в данном случае ~7-8 раз в двойном цикле. И предполагается, что их сумма и каждый промежуточный рез-т в конце сойдётся с итогом НДС. А числа гадкие, и на экране сразу видно навроде ИТОГО=ххх,00 НДС= уу,99 ВСЕГО с НДС= zzz,00 Операция round(a+b+c+d ) не дистрибутивна относительно суммы, и для суммы НДС округлять нужно бы каждое слагаемое. Ну это как "немного изменить последнюю цифру телефонного номера". При том ведь ошибка вылезла на другом значении, потому что слагаемые не округлялись - я не долго думая округлил, решил посмотреть как скажется в других случаях, ткнул в случайное место - а тут такая фигня. Ну то есть хвост вытащил - нос увяз. Всегда сконялся к варианту двойного преобразования по типу: (double)( (__int64) (aa+0.5) + bb ) , но любая правка кроме подмены макроса - это в сотнях мест, и опять поедут старые значения, а вообще тысяча мест, где подобные сложения. Ну неподъёмно это, поэтому я так консервативен в ответах . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 11:54 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
m_Sladouble TO_RUB(double A) { return (int)( A + 0.5 ); }Наверное это лучший вариант. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 11:58 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98m_Sladouble TO_RUB(double A) { return (int)( A + 0.5 ); }Наверное это лучший вариант. Ну и чем он лучший? Разве что побыстрее твоего отработает. Это математическое округление через округление вниз. 1.234999999999999999 округлится до 1.23. Проблемы с точностью тут абсолютно те же что и твоем первом посте. Ты пойми, погрешность она в обе стороны бывает: и в плюс и в минус. У тебя все проблемы в том что в минус ты не учитываешь. В данном случае надо A + 0.5 1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 12:17 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98Ну да, слагаемые должны быть большей точности, чем сумма. Но в данной ветке числа не вычисляются, а много раз складываются готовые НДС из БД, в данном случае ~7-8 раз в двойном цикле. И предполагается, что их сумма и каждый промежуточный рез-т в конце сойдётся с итогом НДС. А числа гадкие, и на экране сразу видно навроде ИТОГО=ххх,00 НДС= уу,99 ВСЕГО с НДС= zzz,00 Если готовые, посчитанные с точностью до копейки, т.е. округленные до копеек при сохранении, то в худшем случае погрешность будет 8/2^53 = 8.8*10^-16, т.е. гарантированно 15 первых знаков точно будут вычислены, дальше надо просто округлить результат до копеек, чтобы окончательно убрать накопленную погрешность. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 12:23 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Dima_T, да, он быстрее в работе и для исправления. В БД всякие значения, рассчитанные в разное время в прошлом: с ошибками и без, с округлениями и без, исправленные и нет. Для некоторых денег это неважно, для других важно, но не фатально. Повторюсь exp98об этом я в курсе ещё с больших машин .... Переделывать тогда уж сотню файлов и процы в БД, да и саму БД переводить на копейки. Это не вариант. Вопрос в том, почему дефайн считает не как я думаю, ну или наоборот.Последнее изначально было единственной целью вопроса. Ну вот ответь мне, какое множество ошибок ты предлагаешь упорядочить 1-го рода, 2-го рода? или некую их взвеш. сумму и тогда в каком соотношении? ну чтоб хотя бы численно ргументировать ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 13:50 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
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 значений будет гарантированно точный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 14:34 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
По поводу округления (понял как точно посчитать), если смещаем на 0,01 копейки (+0.0051), чтобы отрицательные погрешности учесть, то можно смело так округлять числа до Код: plaintext С математикой округления можно еще пооптимизировать, сходу не соображу до скольки можно добавить, вроде 0.0004 (+0.0054) должно тоже точно работать и увеличит макс. значение до 3 602 879 701 896,40 или 15 десятичных знаков. Подзабыл математику :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 14:55 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Это из статистики о принятии и отпрасывании гипотез. В одном случае мы (ошибочно) принимаем некоторые события за истинные. В другом случае (ошибочно) отбрасываем истинные события. У нас есть двоичное число. Используем его в плавающем формате для сравнения. В проге при сравнении мы отождествляем все числа, отличающиеся от некоторого на маленькую дельту. При этом некоторые числа справедливо будут отождествлены, а некоторые - в рез-те погрешностей вычислений. То есть часть чисел будет представлено округлённым справедливо, а часть нет, но нам приходится принимать это как есть. Гипотеза (о справедливости округления) содержит ошибки "одного рода". Остальные числа не пройдут сравнение и не будут округлены аналогично. Соответственно парная первой ггипотеза о ненужности округления этих чисел содержит ошибку "другого рода". Ну и вопрос мой был каких ошибок больше и на сколько: справедливо округлённых или несправедливо неокруглённых, примерно так. А вообще мне сейчас с базой и VS надо копаться, вникать в ответы позднее буду. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.11.2016, 15:04 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Нконец вернулся к этому вопросу. Вот ты писал 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. Моё резюме таково же как выше все и пишут, double - не самый лучший формат для денежных операций. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.01.2017, 19:02 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
exp98, недавно похожая тема была 20077393 , подходит double для денег, но пользоваться им надо аккуратно. Что касается НДС, то там где деление (умножение на нецелое), точность в принципе теряется. Сумма НДС 18%Сумма с НДС1.240.221.461.240.221.461.240.221.46 Итого по столбцам Сумма НДС 18%Сумма с НДС3.720.664.36 Но 18% от 3.72 это 0.67 будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.01.2017, 19:28 |
|
||
|
и снова копейки: #define, С++ , Builder 2009 ?
|
|||
|---|---|---|---|
|
#18+
Ну разумеется аккуратно. Я за себя говорю, в моём случае тогда придётся затормозить ГУИ или же частично переделать фреймворк в денежной части под эффективные алгоритмы, возможно с правками процедур в БД. А параллельно с этим продолжать доработки на прежней схеме. Не до такой же степени я трудоголик. И всем спасибо за варианты и ссылки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.01.2017, 13:19 |
|
||
|
|

start [/forum/topic.php?all=1&fid=57&tid=2018316]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
45ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
65ms |
get tp. blocked users: |
1ms |
| others: | 11ms |
| total: | 159ms |

| 0 / 0 |
