Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы программирования на языке Turbo Prolog.doc
Скачиваний:
56
Добавлен:
09.11.2019
Размер:
563.2 Кб
Скачать

3. Граничное условие рекурсии. Нисходящая и восходящая рекурсии

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

Решить ее позволит утверждение, называемое ГРАНИЧНЫМ УСЛОВИЕМ.

В задаче о вычислении суммы таким условием является

sum_series2(1,1) :- !.

Для ответа на запрос sum_series2(4,X) последовательно вычислялись sum_series2(3,S1), sum_series2(2,S2), sum_series2(1,S3) (граничное условие).

Такая рекурсия называется НИСХОДЯЩЕЙ.

Поступим наоборот: начнем с граничного условия и будем строить решение, пока не получим исходную задачу.

Такая рекурсия называется ВОСХОДЯЩЕЙ.

В таком методе правило sum_series3 должно иметь два дополнительных параметра:

1) указание на размер решенной к данному моменту задачи (число уже просуммированных слагаемых);

2) запись промежуточного решения (уже подсчитанной частичной суммы).

Запрос

sum_series3(1,1,7,X)

включает старое граничное условие, как уже решенную к настоящему моменту задачу.

Новое граничное условие выглядит так:

sum_series3(N,X,N,X):-!.

Правило 3 рекурсии:

/* M-текущее слагаемое, S-частичная сумма, N-последнее слагаемое, X-окончательная сумма */

sum_series3(M,S,N,X):-

M1=M+1,

S1=S+M1,

sum_series3(M1,S1,N,X).

Упражнение 5.2.

Вычислить и напечатать факториал числа 5 с помощью восходящей и нисходящей рекурсии.

4. Программа о подсчете числа точек

/* Программа 5.2 «Подсчет точек». Назначение: */

/*демонстрация использования восходящей рекурсии */

constants

r=2

domains

i=integer

r=real

predicates

show_point

culc_point(i,i,i,i,i,i)

pos_point(i,i,i,r,r,i,i,i)

out_sqr(r,r)

in_circ(r,r)

goal

show_point.

clauses

show_point:-

clearwindow,

% запрос с обнуленными счетчиками точек

culc_point(0,0,0,Sum1,Sum2,Sum3),

write("вне квадрата ",Sum1,

"внутри круга ",Sum2,

"в квадрате вне круга ",Sum3).

% рекурсивное правило

culc_point(C1,C2,C3,Sum1,Sum2,Sum3):-

write(" X? "),readreal(X),

write(" Y? "),readreal(Y),

pos_point(C1,C2,C3,X,Y,S1,S2,S3),!,nl,

% вызов с новыми значениями счетчиков

culc_point(S1,S2,S3,Sum1,Sum2,Sum3).

% выход из рекурсии с накопленными счетчиками

culc_point(C1,C2,C3,C1,C2,C3).

% окончание запросов и отказ процедуры

% pos_point

pos_point(_,_,_,0,0,_,_,_):-!,fail.

% увеличение первого счетчика

pos_point(C1,C2,C3,X,Y,S1,C2,C3):-

S1=C1+1,

out_sqr(X,Y),!,

write(" вне квадрата").

% увеличение второго счетчика

pos_point(C1,C2,C3,X,Y,C1,S2,C3):-

S2=C2+1,

in_circ(X,Y),!,

write("внутри круга").

% увеличение третьего счетчика

pos_point(C1,C2,C3,_,_,C1,C2,S3):-

S3=C3+1,

write("вне круга и внутри квадрата").

% условие для точки вне квадрата

out_sqr(X,Y):-

abs(X)>r;

abs(Y)>r.

% условие для точки внутри круга

in_circ(X,Y):-

X*X+Y*Y<r*r.

/* Конец программы */

Программа 5.2 содержит восходящую рекурсивную процедуру culc_point, благодаря которой происходит подсчет точек.

Первый вызов ее из цели верхнего уровня —

culc_point(0,0,0,Sum1,Sum2,Sum3), где первые три аргумента — текущие значения счетчиков, оставшиеся — конечные значения (сейчас они не имеют никакого значения и являются свободными переменными).

Эта цель сопоставляется с рекурсивным правилом

culc_point(C1,C2,C3,Sum1,Sum2,Sum3), которое

1) запрашивает точку;

2) вызывает pos_point(C1,C2,C3,X,Y,S1,S2,S3), возвращающую новые значения счетчиков S1, S2, S3;

3) вызывает само себя с новыми текущими значениями счетчиков.

На протяжении всех этих вызовов последние три аргумента Sum1, Sum2, Sum3 остаются свободными переменными. Так продолжается до тех пор, пока не вводится точка (0,0).

Правило pos_point(_,_,_,0,0,_,_,_) дает отказ без возможности перехода на другое правило pos_point (комбинация !,fail), и рекурсивное правило culc_point дает отказ. Затем происходит переход на граничное условие culc_point(C1,C2,C3,C1,C2,C3).

Аргументы, предназначенные для конечных значений счетчиков, наконец, перестают быть свободными, — в них копируются текущие значения. После этого цель culc_point(0,0,0,Sum1,Sum2,Sum3) успешно согласуется, происходит печать ответов и выход из программы.

Упражнение 5.3.

Напечатать сумму ряда , вычисленную с заданной точностью eps при фиксированном значении x (сумму вычислить и восходящей, и нисходящей рекурсией).