Тогда наши три правила можно выразить тремя предложениями так:
нод( X, X, X).
нод( X, Y, Д) :-
Х < Y,
Y1 is Y - X,
нод( X, Y1, Д),
нод( X, Y, Д) :-
Y < X,
нод( Y, X, Д).
Разумеется, с таким же успехом можно последнюю цель в третьем предложении заменить двумя:
X1 is Х - Y,
нод( X1, Y, Д)
В нашем следующем примере требуется произвести некоторый подсчет, для чего, как правило,
необходимы арифметические действия. Примером такой задачи может служить
вычисление длины какого-либо списка
; иначе говоря, подсчет числа его элементов. Определим процедуру
длина( Список, N)
которая будет подсчитывать элементы списка Список
и конкретизировать N полученным числом. Как и раньше, когда речь шла о списках, полезно рассмотреть два случая:(1) Если список пуст, то его длина равна 0.
(2) Если он не пуст, то Список = [Голова1 | Хвост] и его длина равна 1 плюс длина хвоста
Хвост.Эти два случая соответствуют следующей программе:
длина( [ ], 0).
длина( [ _ | Хвост], N) :-
длина( Хвост, N1),
N is 1 + N1.
Применить процедуру длина
можно так:?- длина( [a, b, [c, d], e], N).
N = 4
Заметим, что во втором предложении этой процедуры две цели его тела нельзя поменять местами. Причина этого состоит в том, что переменная N1 должна быть конкретизирована до того, как начнет вычисляться цель
N is 1 + N1
Таким образом мы видим, что введение встроенной процедуры
is привело нас к примеру отношения, чувствительного к порядку обработки предложений и целей. Очевидно, что процедурные соображения для подобных отношений играют жизненно важную роль.Интересно посмотреть, что произойдет, если мы попытаемся запрограммировать отношение
длина без использования is. Попытка может быть такой:длина1( [ ], 0).
длина1( [ _ | Хвост], N) :-
длина1( Хвост, N1),
N = 1 + N1.
Теперь уже цель
?- длина1( [a, b, [c, d], e], N).
породит ответ:
N = 1+(1+(1+(1+0)))
Сложение ни разу в действительности не запускалось и поэтому ни разу не было выполнено. Но в процедуре
длина1, в отличие от процедуры длина, мы можем поменять местами цели во втором предложении:длина1( _ | Хвост], N) :-
N = 1 + N1,
длина1( Хвост, N1).
Такая версия длина1
будет давать те же результаты, что и исходная. Ее можно записать короче:длина1( [ _ | Хвост], 1 + N) :-
длина1( Хвост, N).
и она и в этом случае будет давать те же результаты. С помощью
длина1, впрочем, тоже можно вычислять количество элементов списка:?- длина( [а, b, с], N), Длина is N.
N = 1+(1+(l+0))
Длина = 3
Итак:
Для выполнения арифметических действий используются встроенные процедуры.
Арифметические операции необходимо явно запускать при помощи встроенной процедуры
is. Встроенные процедуры связаны также с предопределенными операторами +, -, *, /, div и mod.К моменту выполнения операций все их аргументы должны быть конкретизированы числами.
Значения арифметических выражений можно сравнивать с помощью таких операторов, как <, =< и т.д. Эти операторы вычисляют значения своих аргументов.
Упражнения
3. 16.
Определите отношениеmах( X, Y, Мах)
так, чтобы Мах
равнялось наибольшому из двух чисел Х и Y.Посмотреть ответ
3. 17.
Определите предикатмаксспис( Список, Мах)
так, чтобы Мах
равнялось наибольшему из чисел, входящих в Список.Посмотреть ответ
3. 18.
Определите предикатсумспис( Список, Сумма)
так, чтобы Сумма
равнялось сумме чисел, входящих в Список.Посмотреть ответ
3. 19.
Определите предикатупорядоченный( Список)
который принимает значение истина, если Список
представляет собой упорядоченный список чисел. Например: упорядоченный [1, 5, 6, 6, 9, 12] ).Посмотреть ответ
3. 20.
Определите предикатподсумма( Множ, Сумма, ПодМнож)
где Множ
это список чисел, Подмнож подмножество этих чисел, а сумма чисел из ПодМнож равна Сумма. Например:?- подсумма( [1, 2. 5. 3. 2], 5, ПМ).
ПМ = [1, 2, 2];
ПМ = [2, 3];
ПМ = [5];
. . .
Посмотреть ответ
3. 21.
Определите процедурумежду( Nl, N2, X)
которая, с помощью перебора, порождает все целые числа X, отвечающие условию Nl <=X <=N2.
Посмотреть ответ
3. 22.
Определите операторы 'если', 'то', 'иначе' и ':=" таким образом, чтобы следующее выражение стало правильным термом: