Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Погрешность при вычислениях, геометрическая прогрессия 
V
    Опции темы
Burka
Дата 6.5.2016, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.5.2007

Репутация: нет
Всего: 2



Здравствуйте, я работаю над задачей где нужно вычислять большие значения геометрической прогрессии. Проблема в том что расчет по формуле расходится с расчетами в цикле, накапливается погрешность. Непонятно что правильней считает.  Подскажите как разобраться, что правильней.

code

Первый вариант
Код

double f1(double count, double base, double power)
{
    double Bn = base * pow(power, count - 1);
    double Sn = (base * (1 - pow(power, count))) / (1 - power);
    return Sn;
};


Второй вариант
Код

double f2(double count, double base, double power)
{
    double result = base;
    double current_price = base;

    for (int i = 1; i < int(count); i++)
    {
        current_price *= power;
        result += current_price;
    }

    return result;
}


разница значений выглядит примерно так
Цитата

[0]  -2
[1]  0
[2]  0
[3]  1.77636e-15
[4]  0
[5]  0
[6]  0
[7]  0
[8]  0
[9]  0
[10]  0
[11]  -7.10543e-15
[12]  0
[13]  -1.42109e-14
[14]  -1.42109e-14
[15]  0
[16]  -1.42109e-14
[17]  0
[18]  -2.84217e-14
[19]  -2.84217e-14
[20]  0
[21]  -2.84217e-14
[22]  0
[23]  -5.68434e-14
[24]  0
[25]  5.68434e-14
[26]  5.68434e-14



--------------------
Великие умы обсуждают идеи; средние умы обсуждают события; мелкие умы обсуждают людей.
PM MAIL   Вверх
feodorv
Дата 7.5.2016, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Оба правильны (если не рассматривать случай count == 0). Расхождение имеет смысл нормировать (то есть выводить не абсолютную ошибку, а относительную).


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Burka
Дата 7.5.2016, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.5.2007

Репутация: нет
Всего: 2



Ну этого не может быть потому что при больших числах погрешность сильно увеличивается

Цитата

[287]  -512
[288]  -1024
[289]  -1024
[290]  -1024
[291]  0
[292]  -1024

а это уже существенно. А точнее 300 это даже не большие еще значения

Это сообщение отредактировал(а) Burka - 7.5.2016, 14:37


--------------------
Великие умы обсуждают идеи; средние умы обсуждают события; мелкие умы обсуждают людей.
PM MAIL   Вверх
feodorv
Дата 7.5.2016, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(Burka @  7.5.2016,  14:32 Найти цитируемый пост)
при больших числах погрешность сильно увеличивается

Относительная ошибка какая?

Добавлено через 2 минуты и 7 секунд
Если Вам так важна точность, имеет смысл копать в сторону специализированных библиотек, поддерживающих желаемую точность. Но и скорость вычисления тогда упадет значительно.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Burka
Дата 8.5.2016, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.5.2007

Репутация: нет
Всего: 2



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


--------------------
Великие умы обсуждают идеи; средние умы обсуждают события; мелкие умы обсуждают людей.
PM MAIL   Вверх
baldman88
Дата 8.5.2016, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 3
Всего: 7



Один из самых простых вариантов -- взять какую-нибудь числодробилку и сравнить результаты.
PM MAIL   Вверх
NoNo
Дата 10.5.2016, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 109
Регистрация: 14.11.2006

Репутация: нет
Всего: нет



У меня в универе, однажды проблема была с погрешностью вычислений...(не помню уже задачу, которая была)..помню только то, что проблема заключалась в сокращенных записях операций умножения/деления и.т.д. с присвоением над вещ. числами(у тебя второй вариант). Я даже тогда проводил тесты этого дела(правда сейчас этого не осталось). Так что я предлагаю использовать первый вариант.
P.S. предлагаю тебе прлтестировать твою задачу.....взять второй вариант как есть....и тоже самое, но без сокращенных операций...т.е. заменить  *= на ...=..*.. и проверить результаты сходятся в оом числе и с первым вариантом


Это сообщение отредактировал(а) NoNo - 10.5.2016, 10:25
PM MAIL   Вверх
Alexeis
Дата 10.5.2016, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



В данном случае правильно сказали, что число 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


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Burka
Дата 10.5.2016, 12:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 429
Регистрация: 11.5.2007

Репутация: нет
Всего: 2



Alexeis, cпасибо за подробный ответ


--------------------
Великие умы обсуждают идеи; средние умы обсуждают события; мелкие умы обсуждают людей.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0536 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.