| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Погрешность при вычислениях |
| Автор: Burka 6.5.2016, 12:41 | ||||||
| Здравствуйте, я работаю над задачей где нужно вычислять большие значения геометрической прогрессии. Проблема в том что расчет по формуле расходится с расчетами в цикле, накапливается погрешность. Непонятно что правильней считает. Подскажите как разобраться, что правильней. http://cpp.sh/4uwzi Первый вариант
Второй вариант
разница значений выглядит примерно так
|
| Автор: feodorv 7.5.2016, 13:53 |
| Оба правильны (если не рассматривать случай count == 0). Расхождение имеет смысл нормировать (то есть выводить не абсолютную ошибку, а относительную). |
| Автор: Burka 7.5.2016, 14:32 | ||
Ну этого не может быть потому что при больших числах погрешность сильно увеличивается
а это уже существенно. А точнее 300 это даже не большие еще значения |
| Автор: feodorv 7.5.2016, 15:35 |
Относительная ошибка какая? Добавлено через 2 минуты и 7 секунд Если Вам так важна точность, имеет смысл копать в сторону специализированных библиотек, поддерживающих желаемую точность. Но и скорость вычисления тогда упадет значительно. |
| Автор: Burka 8.5.2016, 12:01 |
| В общем мне надо выбрать из двух этих функций какая точнее считает, видимо из за того что погрешность накапливается то дело в цикле, формула должна считать точнее. Но вот как проверить это пока не понял |
| Автор: baldman88 8.5.2016, 14:43 |
| Один из самых простых вариантов -- взять какую-нибудь числодробилку и сравнить результаты. |
| Автор: NoNo 10.5.2016, 10:22 |
| У меня в универе, однажды проблема была с погрешностью вычислений...(не помню уже задачу, которая была)..помню только то, что проблема заключалась в сокращенных записях операций умножения/деления и.т.д. с присвоением над вещ. числами(у тебя второй вариант). Я даже тогда проводил тесты этого дела(правда сейчас этого не осталось). Так что я предлагаю использовать первый вариант. P.S. предлагаю тебе прлтестировать твою задачу.....взять второй вариант как есть....и тоже самое, но без сокращенных операций...т.е. заменить *= на ...=..*.. и проверить результаты сходятся в оом числе и с первым вариантом |
| Автор: Alexeis 10.5.2016, 11:20 |
| В данном случае правильно сказали, что число double не имеет достаточно разрядности для того, чтобы правильно посчитать такие значения. Так при f1(288, 2, 1.15); получается значение ~ -605 352 050 046 196 131, для точного хранения которого необходимо 59 битное число, тогда как число double имеет всего 52 бита. Т.е. сразу видно, что 7 младших разрядов отсекаются. Это не говоря уже про то, что каждая операция с double числами имеет свою погрешность. В случае цикла мы имеем 288 умножений и столько же сложений. Погрешность даже одной операции довольно значительная. Как минимум последняя десятичная цифра в числе считается неверно. Это 3-4 двоичных разряда. Даже если учесть только эти погрешности, то мы имеем 7 разрядов потерянных при отсечении и в лучшем случае 3 при умножении. Т.е. 10 разрядов - 2^10 = 1024 . Такая вот беглая оценка показывает, что расхождение в 1024 на 288м элементе вполне допустима для чисел double. Если ваш компилятор поддерживает long double c 63 битной точностью и сопроцессор будет настроен на вычисления с этой точностью, то для количества элементов 288 расхождения опять будут минимальными. Добавлено через 3 минуты и 52 секунды Собственно даже гадать нечего, online компилятор поддерживает long double http://cpp.sh/5udj |
| Автор: Burka 10.5.2016, 12:44 |
| Alexeis, cпасибо за подробный ответ |