Вычислить сумму ряда с заданной точностью с помощью рекурсии, Рекурсия |
1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!
Вычислить сумму ряда с заданной точностью с помощью рекурсии, Рекурсия |
dog |
2.02.2010 21:46
Сообщение
#1
|
Новичок Группа: Пользователи Сообщений: 17 Пол: Женский Репутация: 0 |
Вычислить сумму ряда с заданной точностью e(epsilon)>0 Есть решение, нет уверенности, что правильно:
Просьба проверить и поправить, если что неправильно |
TarasBer |
2.02.2010 22:11
Сообщение
#2
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
Так ты сначала у себя запусти, проверь. Ты ж не проверял.
Если 1/(w*z) >= e, то, во-первых, делается рекурсивный вызов с теми же параметрами (что приведёт к переполнению стека - рекурсии неоткуда выйти), а во-вторых, в результат ничего не записывается. И, в третьих, с математической точки зрения то, что очередной член ряда стал меньше епсилон, ещё отнюдь не означает, что мы просуммировали ряд с достаточной точностью (я так могу гармонический ряд "просуммировать", ага). Вообще принято сначала рассчитать оценку погрешности через очередной член ряда (для каждого ряда оценка своя), а потом через эту оценку и определять, достигли мы точности, или нет. -------------------- |
dog |
2.02.2010 23:34
Сообщение
#3
|
Новичок Группа: Пользователи Сообщений: 17 Пол: Женский Репутация: 0 |
Она при некоторых значениях епсилон выдает всегда один и тот же ответ, а при некоторых действительно происходит переполнение стека.
А если так?
Ну на самом деле сложная задача, ряды да еще и рекурсия. Сообщение отредактировано: dog - 2.02.2010 23:36 |
TarasBer |
2.02.2010 23:53
Сообщение
#4
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
Дык проверь сначала, чего меня спрашивать. От замены двух букв на равные им ничего не изменится, очевидно.
-------------------- |
volvo |
3.02.2010 0:52
Сообщение
#5
|
Гость |
Цитата Ну на самом деле сложная задача, ряды да еще и рекурсия. На самом деле рекурсия - проще, чем итерация. Если понимаешь сам принцип написания рекурсивных функций. Не веришь? Смотри:1. Для начала определимся с тем, что наша рекурсия будет принимать, и что - возвращать... Ну, возвращать она будет Real, это очевидно. А принимать - 2 числа которые стоят в знаменателе, так? Не совсем. Зачем передавать их оба, если можно передать одно, только X, а зная X вычислять Y когда нужно?. Итак, с заголовком определились: function f(X: integer; eps: real): real; 2. Теперь делаем то, без чего работающей рекурсивной функции не может существовать - опишем условие выхода из функции. Когда надо выходить? Правильно, если 1/(x * (x+2)) станет меньше eps... Так и запишем... Хм. А что запишем? Что должно вернуться, когда пришло время выйти из функции? Функция у нас считает сумму ряда, значит надо вернуть какое-то значение, которое эту сумму не испортит. Такое значение у нас только одно: ноль... Вот, значит, и пишем условие выхода: if 1/(x * (x+2)) < eps then f := 0 3. Ну хорошо, если условие выполнилось, понятно что будет. А если НЕ выполнилось - что делать? Словами описываем алгоритм: сложить значение текущего члена с суммой последующих. Так? Так... А на Паскаль перевести? else { Не выполнилось условие } Итого - собираем все вместе: function f(X: integer; eps: real): real; Вот и все... Сложно? По-моему, нет... НО. (опять это НО, я всегда ловлю себя на мысли, что слишком часто получаются какие-то оговорки, ничего не бывает просто и без проблем). Эта функция будет работать, но до определенного предела. Где предел, и почему функция не работает дальше (в настройках компилятора выставить все Run-time проверки !!!) - вот вопрос... Сообщение отредактировано: volvo - 25.02.2010 14:31 |
Unconnected |
3.02.2010 7:43
Сообщение
#6
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Наверное, проблема с максимальной точностью значения, которое может принять real?)
-------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
Client |
3.02.2010 15:11
Сообщение
#7
|
Профи Группа: Пользователи Сообщений: 865 Пол: Мужской Реальное имя: Вячеслав Репутация: 20 |
ошибка в этом месте
if 1/(x * (x+2)) < eps then f := 0проиходит тогда, когда знаменатель становится 33489 и х=183 (видимо операцию, значение которой больше 32767, в рекурсии нельзя выполнить).Поэтому, делаю проверку на вхождение в дипазон типа integer. if (sqrt(maxint)<x ) then f:=0 Добавлено через 14 мин. это я так думаю Сообщение отредактировано: Client - 3.02.2010 15:16 Эскизы прикрепленных изображений |
volvo |
3.02.2010 18:46
Сообщение
#8
|
Гость |
Оба предыдущих ответа не содержат правильной идеи... Во-первых, Real-а вполне себе хватает. А во-вторых,
Цитата видимо операцию, значение которой больше 32767, в рекурсии нельзя выполнить - в рекурсии можно вычислять и гораздо бОльшие результаты. Рекурсия в этом смысле ничем от итерации не отличается.Думаем дальше |
TarasBer |
3.02.2010 18:46
Сообщение
#9
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> else f := (1/(x * (x+2))) + f(x + 4, eps);
Тут какая-то неприятность со стеком сопроцессора должна произойти. Надо
-------------------- |
volvo |
3.02.2010 18:52
Сообщение
#10
|
Гость |
Цитата Тут какая-то неприятность со стеком сопроцессора должна произойти. Ничего не должно произойти, без разбиения все прекрасно вычисляется. Можно, конечно сделать то, что ты написал, но это не имеет решающего значения, можно обойтись и без этого.Еще идеи есть? Client, ведь ты показал скриншот, который должен был заставить тебя задуматься кое над чем... Чего ты не задумался? P.S. А где, собственно, топикстартер? Ей не интересно? Или ждет, когда всё решат, все ошибки исправят, а потом втихую заберет, и все, добилась своего? |
TarasBer |
3.02.2010 18:55
Сообщение
#11
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
Тут про переполнение типа говорили.
Я бы написал дробь как (1/x)*(1/(x+2)) -------------------- |
volvo |
3.02.2010 19:03
Сообщение
#12
|
Гость |
Цитата Я бы написал дробь как Хм... (Показать/Скрыть)
|
Client |
3.02.2010 19:06
Сообщение
#13
|
Профи Группа: Пользователи Сообщений: 865 Пол: Мужской Реальное имя: Вячеслав Репутация: 20 |
x * (x+2)ошибка именно здесь, даже без деления. ты про 1 картинку на 1 скрине? |
TarasBer |
3.02.2010 19:15
Сообщение
#14
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
[offtop]
> Вот от тебя (с твоей тягой к оптимизации) я это ожидал услышать меньше всего. Моя тяга к оптимизации упала в обморок при виде вычисления ряда через рекурсию и валяется без сознания, поэтому молчит. [/offtop] Проверил у себя. Вываливается именно с ~8 итераций. А так - не вываливается: tmp_f := f(x + 4, eps); f := tmp_f + 1/(longint(x)*(x+2)) -------------------- |
dog |
5.02.2010 1:18
Сообщение
#15
|
Новичок Группа: Пользователи Сообщений: 17 Пол: Женский Репутация: 0 |
P.S. А где, собственно, топикстартер? Ей не интересно? Или ждет, когда всё решат, все ошибки исправят, а потом втихую заберет, и все, добилась своего? volvo, спасибо за простое и понятное объяснение рекурсии! Тут тут я просто неожиданно как-то даже, что рекурсия так просто. Просто в легком шоке даже немножко от простоты рекурсии. Над "подводным камнем" думаю тоже. |
dog |
5.02.2010 1:54
Сообщение
#16
|
Новичок Группа: Пользователи Сообщений: 17 Пол: Женский Репутация: 0 |
f := tmp_f + 1/(longint(x)*(x+2)) То есть как я понимаю при определенной величине происходит обыкновенное деление на ноль? Поэтому программа и вылетает? А ноль образуется в результате переполнения переменной x? Вот замена входного параметра eps в функции f на double по моему немножко отодвинула порог вылета, но кардинально вопрос не решила. Будем думать дальше. Сообщение отредактировано: dog - 5.02.2010 1:56 |
TarasBer |
6.02.2010 14:29
Сообщение
#17
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
> Поэтому программа и вылетает?
Нет, у меня программа вылетала из-за переполнения стека сопроцессора. Классический пример - рекурсивное вычисление факториала. Тут где-то на форуме есть пример с объяснением, поищите. -------------------- |
Client |
7.02.2010 19:18
Сообщение
#18
|
Профи Группа: Пользователи Сообщений: 865 Пол: Мужской Реальное имя: Вячеслав Репутация: 20 |
volvo, кажется больше идей нету... тут приведение типов как в С может и помогло бы...
хотелось бы узнать, в чем кроется секрет. |
volvo |
7.02.2010 23:03
Сообщение
#19
|
Гость |
Приведение типов не нужно... Явное по крайней мере. Приведи неявно.
+ к этому - пока никто не показал окончательный код, который не будет вылетать при eps = 1E-8 независимо от настроек компилятора Турбо-Паскаля. То есть, независимо от того, выбран у меня режим эмуляции сопроцессора или режим 8087/80287... Окончательную версию в студию можно? А то выцеживаете по одной строке... Я что, одну строку привел? |
Krjuger |
7.02.2010 23:16
Сообщение
#20
|
Профи Группа: Пользователи Сообщений: 652 Пол: Мужской Реальное имя: Алексей Репутация: 20 |
Я думаю,что для начала надо разобраться почему вылетело RT215(Arithmetic overflow),а не RT205(Floating point overflow).
Arithmetic overflow - целочисленное переполнение - возникает при выполнении арифметической операции над целыми числами, когда результат операции выходит за границы соответствующего типа. Как говорил Client, при 33к с копейками в знаменателе уже происходит вылет, при этом есть тип Short, который может содержать целые числа о -32,768 до 32,767.Принципи вот из-за этого и происходит переполнение,но для мен лично небольшая загадка почему именно тип short береться для выполнения операций,а не сам integer. Это лиш мои догадки,скорее всего я не прав. |
Текстовая версия | 28.04.2024 7:09 |