Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
source_examples.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
306.69 Кб
Скачать

Пример 5.2. Вычисление факториала

Создадим предикат, который будет вычислять по натуральному числу его факториал.

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

fact(1,1). /* факториал единицы равен единице */

fact(N,F):-

N>1, /* убедимся, что число больше единицы */

N1 is N-1,

fact(N1,F1), /* F1 = факториалу числа, на единицу меньшего исходного числа */

F is F1*N. /* факториал исходного числа = произведению F1 на само число */

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

fact(1,1):-!. /* условие останова рекурсии */

fact(N,F):-

N1 is N-1,

fact(N1,F1), /* F1 = факториалу числа, на единицу меньшего исходного числа */

F is F1*N./* факториал исходного числа равен произведению F1 на само число */

6. Хвостовая рекурсия Пример 6.1. Вычиление факториала с с использованием хвостовой рекурсии

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

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

Вся процедура будет выглядеть следующим образом:

fact2(N,F,N,F):-!. /* останавливаемся, когда третий аргумент равен первому*/

fact2(N,F,N1,F1):-

N2 is N1+1, /* N2 - следующее натуральное число после числа N1 */

F2 is F1*N2, /* F2 - факториал N2 */

fact2(N,F,N2,F2).

/* рекурсивный вызов с новым натуральным числом N2 и соответствующим ему

посчитанным факториалом F2 */

Остановить рекурсию можно, воспользовавшись отсечением в базисе рекурсии, как это было сделано выше, или добавив в начало второго предложения сравнение N1 с N.

Пример 6.2. Вычисление чисел Фибоначчи

Еще одна классическая задача, имеющая рекурсивное решение, связна с вычислением так называемых чисел Фибоначчи. Числа Фибоначчи можно определить так: первое и второе числа равны единице, а каждое последующее число является суммой двух предыдущих. Соответственно, третье число Фибоначчи будет равно двум, четвертое равно трем (сумма второго числа (один) и третьего числа (два)), пятое - пяти (сумма третьего и четвертого чисел, то есть двух и трех), шестое - восьми (сумма четвертого и пятого, трех и пяти) и т.д.

Базисов рекурсии в данном случае два. Первый будет утверждать, что первое число Фибоначчи равно единице. Второй базис - аналогичное утверждение про второе число Фибоначчи. Шаг рекурсии также будет необычным, поскольку будет опираться при вычислении следующего числа Фибоначчи не только на предшествующее ему число, но и на предшествующее предыдущему числу. В нем будет сформулировано, что для вычисления числа Фибоначчи с номером N сначала нужно вычислить и сложить числа с номерами N-1 и N-2.

Записать эти рассуждения можно так:

fib(1,1):- !. /* первое число Фибоначчи равно единице */

fib(2,1):- !. /* второе число Фибоначчи равно единице */

fib(N,F) :-

N1 is N-1, fib(N1,F1), /* F1 это N-1-е число Фибоначчи */

N2 is N-2, fib(N2,F2), /* F2 это N-2-е число Фибоначчи */

F is F1+F2. /* N-е число Фибоначчи равно сумме N-1-го и N-2-го чисел */

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]