![]() |
|
Модераторы: bsa |
![]()
|
|
| konstantusha |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 10.10.2012 Репутация: нет Всего: нет |
Здравствуйте! Возникла проблема с такой задачей: нужно подсчитывать произведение а[k]-тых пока а[k]-а[k-1]>eps. а[k]=а[k-1]+а[k-1]/2^(k-1), k=2,3.... a[0]=a[1]=1. Написанная мною программа работает, но начиная с произведения a[1]*..*a[4] подсчитывает с неточностью, которая в последующем увеличивается. Подскажите пожалуйста, в чем причина и как это исправить?
|
|||
|
||||
| kosmonaFFFt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 538 Регистрация: 14.4.2008 Где: Иннополис Репутация: нет Всего: 5 |
Самый простой способ увеличить точность - использовать double вместо float, но все равно точных вычислений не получится - будет погрешность, которая будет накапливаться с количеством вычислений...
-------------------- ![]() |
|||
|
||||
| konstantusha |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 10.10.2012 Репутация: нет Всего: нет |
Я пробовала это делать, особо не помогло.
|
|||
|
||||
| NoviceF |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 313 Регистрация: 13.3.2012 Где: Ростов-на-Дону Репутация: 2 Всего: 2 |
Вот здесь эпичный топик на тему http://forum.vingrad.ru/forum/topic-355758.html
|
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 12 Всего: 72 |
По возможности, не пользуйся pow. Он вычисляется через логарифмы.
Замени его на умножение или сдвиг целого (если k <= 31) |
|||
|
||||
| konstantusha |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 10.10.2012 Репутация: нет Всего: нет |
math64, вы имеете ввиду вычисление степени с помощью цикла?
|
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
konstantusha, он имеет в виду, использование операции сдвига вместо вызова функции pow(). Сдвиг единицы на n бит влево (1 << n) эквивалентен возведению 2 в степень n.
|
|||
|
||||
| konstantusha |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 10.10.2012 Репутация: нет Всего: нет |
Попробовала заменить pow сдвигом влево - ничего не изменилось..
|
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 12 Всего: 72 |
Сдвигать влево можно только до 31 степени. А можно считать в цикле.
a[k]=а[k-1]+а[k-1]/2^(k-1) можно заменить на a[k]=а[k-1]*(1+1/2^(k-1)) b[2] = (2+1)/2 = 1.5; a[2] = a[1]*b[2]; b[3] = (b[2] + 1)/2 = 1.25; a[3] = a[2]*b[3]; Но так b[k] очень быстро станет 1. или 1+EPS (в зависимости от правил округления) Можно прологарифмировать: lnA[2] = lnA[1]+ln(1+0.5); lnA[3] = lnA[2]+ln(1+0.25); lnA[4] = lnA[3]+ln(1+0.125); ... lnP = lnA[1] + lnA[2] + lnA[3] + ...; lnP = ln(1+0.5)*N + ln(1+0.25)*(N-1) + ln(1+0.125)*(N-2) + ...; P = exp(lnP); Для вычисления логарифма нужно вычислять ln(1+x) для малых x без потери точности. Это сообщение отредактировал(а) math64 - 10.10.2012, 12:57 |
|||
|
||||
| Silent |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 252 Регистрация: 3.10.2006 Репутация: 1 Всего: 9 |
konstantusha, попробую вас удивить, но применительно к float и double a+b не всегда равняется b+a
Посмотрите результаты этой программы, и поймете:
Результаты:
Первый результат получается, если я начинаю перемножать с малых чисел, второй результат - если делаю как автор, ну а третий результат - авторский (почти - поставлен тип double). На float'ах же все везде одинаково - 74163.30468750000000000000 |
||||
|
|||||
| Silent |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 252 Регистрация: 3.10.2006 Репутация: 1 Всего: 9 |
math64, а нельзя ли предлагаемую формулу представить уравнением производящей функции? (например, как здесь) И тогда проблемы точности вычисления произведения ряда станут проблемой вычисления формулы, что неизмеримо проще. не?
|
|||
|
||||
| konstantusha |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 6 Регистрация: 10.10.2012 Репутация: нет Всего: нет |
Silent, math64 спасибо большое) Наконец-то разобралась, с вашей помощью)
|
|||
|
||||
| math64 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2505 Регистрация: 12.4.2007 Репутация: 12 Всего: 72 |
||||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |