Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/120: Рейтинг темы: голосов - 120, средняя оценка - 4.59
 Аватар для Valera59
1 / 1 / 0
Регистрация: 12.08.2012
Сообщений: 20

Рекурсия, факториал

03.09.2012, 18:35. Показов 25368. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Недавно увидел как пример рекурсии:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;
 
int f(int n)
{
    if (n == 1)
        return 1;
    return f(n-1)*n;
}
 
int main()
{
    setlocale(0,"");
 
    cout<<f(5);
 
    cin.get();
}
программа должна выдавать факториал 5 и она действительно это делает но я не могу понять почему она это делает.Точнее не понимаю строку 8 чему равно f, и почему программа выполняет ее 5 раз?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.09.2012, 18:35
Ответы с готовыми решениями:

Рекурсия, двойной факториал
Описать рекурсивную функцию Fact2 (N) действительного типа, вычисляющую значение двойного факториала N !! = N * (N - 2) * (N - 4) ......

Рекурсия: факториал числа
#include &lt;iostream&gt; using namespace std; int factorial(int n); int main() { cout &lt;&lt; &quot;at main&quot; &lt;&lt; endl; cout &lt;&lt;...

Двойной факториал VS рекурсия
Доброго времени суток. Программа которая считает двойной факториал есть: int df(int x) { if (x&lt;3) { return x; } ...

14
Twilight Parasite
 Аватар для Invader_Zim
154 / 150 / 7
Регистрация: 21.07.2011
Сообщений: 908
03.09.2012, 18:38
все элементарно, когда n=1 то выход из функции, иначе фигарим ту функцию еще раз, только с другим аргументом
1
 Аватар для Valera59
1 / 1 / 0
Регистрация: 12.08.2012
Сообщений: 20
03.09.2012, 18:42  [ТС]
Цитата Сообщение от Invader_Zim Посмотреть сообщение
все элементарно, когда n=1 то выход из функции, иначе фигарим ту функцию еще раз, только с другим аргументом
Спасибо дошло!
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
03.09.2012, 20:11
Вот еще хороший пример использования рекурсии
C
1
2
3
4
5
6
7
8
9
Peano(unsigned int n)
{
   if (n==0) return 0;
   return Peano(n-1) + 1;
}
main()
{
  cout<< Peano(5);
}
Должен выдать 5.
Правда, не проверял.
0
Twilight Parasite
 Аватар для Invader_Zim
154 / 150 / 7
Регистрация: 21.07.2011
Сообщений: 908
03.09.2012, 20:15
и самое банальное вешающее систему:

C++
1
int main(){double *p=new[1000];main();}
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.09.2012, 21:22
Цитата Сообщение от Valera59 Посмотреть сообщение
Недавно увидел как пример рекурсии:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;
 
int f(int n)
{
    if (n == 1)
        return 1;
    return f(n-1)*n;
}
 
int main()
{
    setlocale(0,"");
 
    cout<<f(5);
 
    cin.get();
}
программа должна выдавать факториал 5 и она действительно это делает но я не могу понять почему она это делает.Точнее не понимаю строку 8 чему равно f, и почему программа выполняет ее 5 раз?
Valera59, как я понимаю, функция это ссылка на возвращаемое значение, если требуется результат (rvalue). Поэтому каждый раз этот адрес заносится в стек, как и инструкция умножить на n и следует новый вызов. Пока не будет достигнут return. После этого вычисления проводятся в обратном порядке (как в польской нотации), то есть 1*2*3*4*5. Единица умножается на n 5 раз, но n каждый раз на 1 больше (как и сохранялось). То есть стек выгружается (исполняется) пока не будет достигнут адрес первого (внешнего) вызова.

Не по теме:

Может сумбурно как-то сказал.



Добавлено через 16 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Valera59, как я понимаю, функция это ссылка на возвращаемое значение, если требуется результат (rvalue). Поэтому каждый раз этот адрес заносится в стек, как и инструкция умножить на n и следует новый вызов.
Правильно скорее:
Valera59, как я понимаю, функция это возвращаемое значение, если требуется результат (rvalue).
Поскольку вызывая себя функция не возвращает значение то в стек заносится инструкция умножить на n и следует новый вызов.
Насочинял...
1
Эксперт С++
 Аватар для Thinker
4267 / 2241 / 203
Регистрация: 26.08.2011
Сообщений: 3,802
Записей в блоге: 5
03.09.2012, 22:16
Вот неплохой пример с рекурсией
https://www.cyberforum.ru/post3307293.html
начните с простого. вывод чисел от 1 до n рекурсивно. найти сумму от 1 до n рекурсивно и т.д.
0
Day
 Аватар для Day
1180 / 990 / 83
Регистрация: 29.10.2009
Сообщений: 1,385
05.09.2012, 01:02
Цитата Сообщение от Invader_Zim Посмотреть сообщение
и самое банальное вешающее систему:

Код C++
Тут вы совершенно правы. Рекурсия - чрезвычайно изящная, но и столь же опасная штука. Я прекрасно понимаю стремление преподавателей обьяснить ее на несколько экзотичном факториале. Но сам, конечно, никогда в жизни вещи, которые можно вычислить иттерационно, не стану делать рекурсивно. Рекурсия использует стек, чье поведение слабо контролируется, и который жрет самое дорогое - память (причем, бесконтрольно). Ну что произойдет, если я иттерационной функции fact дам на вход слишком большое число? Ну, будет неверный результат (такой же будет и у рекурсивной, если она сумеет доработать). А рекурсивная fact просто вылетит с трудно понимаемыми сообщениями.
Кстати, Д.Кнут в своей попытке энциклопедии явно рекурсивные алгоритмы реализовывал БЕЗ рекурсии! Правда, ему пришлось вводить такие массивы, как Stek1, StekOut и т.п...

Добавлено через 12 минут
Не думаю, что Д.Кнут не знал о рекурсии. Конечно, прекрасно знал! Но он рассматривал свою энциклопедию, как Учебник, и не хотел учить ОПАСНОМУ.
А вот чего он, кажется, не знал, так это СТРУКТУР (ничего не говоря уже о классах), поэтому его великолепные алгоритмы выглядят весьма неуклюже.
2
 Аватар для Intel~lect
137 / 126 / 14
Регистрация: 03.07.2012
Сообщений: 355
05.09.2012, 16:22
Valera59, Вот небольшую схему сделал что происходит при вызове функции f(5) А вместо всех переменных сразу подставил их числовые значения.
Миниатюры
Рекурсия, факториал  
2
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.09.2012, 17:56
Да, все это складывается и раскручивается в обратном порядке.
Я тут порезвился на тему заполнения и выгрузки стека вызовов, при рекурсии. Вы уж простите. Бываю несдержан. Конечно, теоретически (гипотетически), мудрый компилятор смог бы скомпилировать даже инлайн-функцию, в последовательный код при, наперед, известном количестве рекурсий (тривиально и не бывает), но на практике даже это, скорее всего не случается. Поэтому использование стека, путем сохранения промежуточных результатов, напоминает фрагменты активационных записей для нерекурсивных (обычных) функций. При итеративных (последовательных) вызовах обычных функций, заполнение и очистка стека происходит обычным образом и это безопаснее.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.09.2012, 18:07
Invader_Zim, Даже не в том дело, что код вешает систему (хотя определенно повесит), проблема больше в том, что вызов main-а явно - UB, если говорить о С++.
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.09.2012, 19:43
Цитата Сообщение от IGPIGP Посмотреть сообщение
Поэтому использование стека, путем сохранения промежуточных результатов, напоминает фрагменты активационных записей для нерекурсивных (обычных) функций.
Не напоминает, а это они есть: записи активаций, они же фреймы стека, хранящие локальные переменные функций, которые ещё не завершили работу (активны) и могут вернуть результат.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.09.2012, 21:27
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Не напоминает, а это они есть: записи активаций, они же фреймы стека, хранящие локальные переменные функций, которые ещё не завершили работу (активны) и могут вернуть результат.
Наверное. Но очистка от такой записи происходит лишь когда функция полностью заканчивает вызов. То есть когда функция с типом возврата выполняет команду return. А в записи ведь не только локальные переменные и аргументы. Хорошо когда как в функции n! одна локальная переменная n, а если там, хотя бы, более или менее, сложное арифметическое выражение из локальных переменных? Вообще, у меня сложилось впечатление, что рекурсия реализована для сохранения возможностей С, где ее мощь проявляется в работе с битами и количество вызовов ограничено разрядностью обрабатываемого числа, например. А n! - удобный пример для объяснения и понимания.
0
~ Эврика! ~
 Аватар для OhMyGodSoLong
1258 / 1007 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
05.09.2012, 21:41
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от IGPIGP Посмотреть сообщение
А n! - удобный пример для объяснения и понимания.
Лично я считаю это ужасным примером. Хуже может быть только
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool isOdd(unsigned);
 
bool isEven(unsigned x)
{
  if (x == 0) {
    return true;
  }
  else {
    return !isOdd(x - 1);
  }
}
 
bool isOdd(unsigned x)
{
  if (x == 1) {
    return true;
  }
  else {
    return !isEven(x - 1);
  }
}
Просто потому, что что-то можно выразить рекурсией, ещё не стоит так действительно делать. В императивных языках вроде Плюсов есть родные циклы, в которых факториал определяется не хуже как произведение чисел от единицы до n.

Ещё можно понять чисто функциональные языки, где циклы выражаются через хвостовую рекурсию, и использование факториала для объяснения хвостовой и не хвостовой рекурсии и т. п. Но не императивный Си.

Лучше бы показывали рекурсию на естественно рекурсивных вещах: qsort, ханойских башнях, поиске в дереве/графе.
3
Day
 Аватар для Day
1180 / 990 / 83
Регистрация: 29.10.2009
Сообщений: 1,385
05.09.2012, 23:22
~OhMyGodSoLong~, Именно это я и хотел сказать
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.09.2012, 23:22
Помогаю со студенческими работами здесь

Описать рекурсивные функции вещественного типа, вычисляющие факториал и двойной факториал заданного числа
Описать рекурсивные функции Fact(N) и Fact2(N) вещественного типа, вычисляющие значения факториала N! и двойного факториала N!!...

Факториал
Задано целое положительное число n. Определить значение выражения: P=\frac{\sum_{i=0}^{n-1}i+1}{(2n)!} Вот код программы: ...

Факториал
Как написать программу для вычисления n факториал

Факториал
Помогите написать программу: Составить функцию, которая вычисляет сумму К слагаемых. В вызывающей функции main() организовать контроль...

Факториал
Элементарный код для того чтобы узнать ФАКТОРИАЛ числа.:D #include &lt;iostream&gt; using namespace std; long long Factorial (int N) { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru