» » »

Язык Prolog. Арифметические действия.

Язык Prolog. Арифметические действия

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

+ сложение

- вычитание

* умножение

/ деление

mod модуль, остаток от целочисленного деления.

Следующий вопрос - наивная попытка произвести арифметическое действие:

?- Х =1+ 2

Пролог-система «спокойно» ответит

Х = 1+2

а не Х=3, как возможно ожидалось. Причина этого проста: выражение 1+2 обозначает лишь прологовский терм, в котором + является функтором, а 1 и 2 - его аргументами. В вышеприведенной цели нет ничего, что могло бы заставить систему выполнить операцию сложения. Для этого в Прологе существует специальный оператор is (есть). Этот оператор заставит систему выполнить вычисление. Таким образом, чтобы правильно активизировать арифметическую операцию надо написать

?- Х is 1 + 2

Вот теперь ответ будет

Х=3

Сложение здесь выполняется специальной процедурой, связанной с оператором +. Мы будем называть такие процедуры встроенными.

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

?- Х is 3 / 2,

Y is 3 // 2.

ответ должен быть такой

Х = 1.5

Y = 1.

Левым аргументом оператора is является простой объект. Правый аргумент - арифметическое выражение, составленное с помощью арифметических операторов, чисел и переменных. Поскольку оператор is запускает арифметические вычисления, к моменту начала вычисления этой цели все ее переменные должны быть конкретизированы какими-либо числами. Приоритеты этих предопределенных операторов выбраны с таким расчетом, чтобы операторы применялись к аргументам в том порядке, который принят в математике. Чтобы изменить обычный порядок вычислений, применяются скобки (тоже, как в математике). Заметьте, что +, -, *, /, // определены как yfx, что определяет порядок их выполнения слева направо. Например,

Х is 5 - 2 -1

понимается как

Х is (5 -2) - 1

Арифметические операции используются также и при сравнении числовых величин. Мы можем, например, проверить, что больше 10000 или результат умножения 277 на 37 с помощью цели

?- 277 * 37 > 10000

yes

Заметьте, что так же как и is, оператор `>' вызывает выполнение вычислений.

Предположим, у нас есть программа, в которую входят отношения рожд, связывающее имя человека с годом его рождения. Тогда имена людей, родившихся между 1950 и 1960 годами включительно, можно получить при помощи такого вопроса:

?- рожд( Имя, Год),

Год >= 1950,

Год <= 1960.

Ниже перечислены операторы сравнения

X > Y X больше Y

X < Y X меньшеY

X >= Y X больше или равенY

X =< Y X меньше или равенY

X =:=Y величины X и Yсовпадают (равны)

X =\=Y величины X иYне равны

Обратите внимание на разницу между операторами сравнения `=' и `=:=', например в таких целях как X = Y и X =:= Y. Первая цель вызовет сопоставление объектов X и Y, и если X и Y сопоставимы, возможно приведет к конкретизации каких-либо переменных в этих объектах. Никаких вычислений при этом производиться не будет. С другой стороны X =:= Y вызовет арифметическое вычисление и не может привести к конкретизации переменных. Это различие можно проиллюстрировать следующими примерами

?- 1+2 =:= 2+1

yes

? - 1+2 =2+1

no

?- 1 + A = B + 2

A = 2

B =1.

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

Если заданы два целых числа Х иY, то их наибольший общий делитель Д можно найти, руководствуясь следующими тремя правилами:

1) Если Х иY равны то Д равен Х.

2) Если Х >Y, то Д равен наибольшему общему делителю Y и разности Х - Y.

3) Если Y < Х, то формулировка аналогична правилу 2), если Х иY поменять в нем местами.

На примере легко убедиться, что эти правила действительно позволяют найти наибольший общий делитель. Выбрав, скажем, Х=20 и Y=25 мы руководствуясь приведенными правилами, после серии вычитаний получим Д=5.

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

длина( Список, N)

Которая будет подсчитывать элементы списка Список и конкретизировать N полученным числом. Как и раньше. Когда речь шла о списках, полезно рассмотреть два случая:

1) Если список пуст, то его длина равна 0.

2) Если список не пуст, то Список = [Голова| Хвост] и его длина равна 1 плюс длина хвоста Хвост.

Эти два случая соответствуют следующей программе:

длина([],0).

длина([_| Хвост], N):-

длина( Хвост, N1) ,

N is 1 + N1.

Применить процедуру длина можно так:

?- длина( [a,b, [c,d], e], N).

N=4

Заметим, что во втором предложении этой процедуры две цели его тела нельзя поменять местами. Причина состоит в том, что переменная N1 должна быть конкретизирована до того, как начнет вычисляться цель

N is 1+N1

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

Итак

· Для выполнения арифметических действий используются встроенные процедуры.

· Арифметические операции необходимо явно запускать при помощи встроенной процедуры is. Встроенные процедуры связаны также с предопределенными операторами +, -, *, /, // и mod.

· К моменту выполнения операций все их аргументы должны быть конкретизированы числами.

· Значения арифметических выражений можно сравнивать с помощью таких операторов, как <, =< и т.д. Эти операторы вычисляют значения своих аргументов.


Друзья! Приглашаем вас к обсуждению. Если у вас есть своё мнение, напишите нам в комментарии.