Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
и снова копейки: #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/moderation_log.php?user_name=Jonny]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
get settings: |
11ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
54ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
55ms |
get tp. blocked users: |
1ms |
| others: | 439ms |
| total: | 620ms |

| 0 / 0 |
