Шаг 51.
Основы логического программирования.
Сравнение

    На этом шаге мы рассмотрим сравнение.

    Пролог может сравнивать арифметические выражения так же, как символы, сроки и идентификаторы. Следующее выражение в Прологе эквивалентно выражению: "Сумма X плюс 4 меньше 9 минус Y".

    X+49-Y

    Оператор отношения "меньше чем" (<) показывает отношение между двумя выражениями: X+4 и 9-Y.

    Пролог использует инфиксную нотацию, которая означает, что оператор располагается между операндами (X+4) вместо того, чтобы предшествовать им (+(X,4)). Полный ряд отношений, разрешенных в Прологе, приведен в таблице 1.

Таблица 1. Операторы отношения
Идентификатор Отношение Идентификатор Отношение
< Меньше > Больше
<= Меньше или равно >= Больше или равно
= Равно <> или >< Не равно

Равенство и предикат равенства

    В Прологе такие операторы, как N=N1-2 показывают отношение между тремя объектами (N,N1 и 2) или отношение между двумя объектами (N и величиной N1-2). Если N еще свободно, оператор может быть удовлетворен присвоением N значения выражения N1-2. Это приблизительно соответствует тому, что в других языках программирования называется оператором присваивания. Заметим, что поскольку N1 является частью вычисляемого выражения, оно всегда должно быть определено (т.е. должно быть связано со значением).

    Когда вы для сравнения вещественных величин используете предикат равенства (=), нужно позаботиться о том, чтобы приближенное представление вещественных чисел не привело к непредсказуемым результатам. Например, цель

    7/3*3=7

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

   predicates
      test(real,real)
   clauses
      test(X,X):-!,
         write("ok\n").
      test(X,Y):-
         Diff=X-Y,
         write(X,"<>",Y,"\nX-Y=",Diff,'\n').
   goal
      X=47,
      Y=4.7*10,
      test(X,Y).
    Текст этой программы можно взять здесь.

    Результат будет следующий:

    47<>47
    X-Y=7.1054273576E-15

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

    Приведем следующий пример:

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

    A*Х*Х+В*Х+С=0

    Наличие решений зависит от значения дискриминанта D, определяемого как

    D=В*В-4*А*С

    В данном случае:

  1. D>0 - означает, что существует два различных решения;
  2. D=0 - означает, что существует единственное решение;
  3. D<0 - означает, что решений нет, если X - вещественное (могут быть одно или два комплексных решения).
   predicates
      solve(real,real,real)
      reply(real,real,real)
      mysqrt(real,real,real) 
      equal(real,real)
   clauses
      solve(A,B,C):-
         D=B*B-4*A*C,
         reply(A,B,D),nl.
      reply(_,_,D):-
         D<0,
         write("No solution"), !.
      reply (A,B,D):-
         D=0,
         X=-B/(2*A),
         write("x=", X),!.
      reply(A,B,D):-
         mysqrt(D,D,SqrtD),
         X1=(-B+SqrtD)/(2*A),
         X2=(-B-SqrtD)/(2*A),
         write("Xl = ",X1," and X2 = ", X2).
      mysqrt(X,Guess,Root):-
         NewGuess=Guess-(Guess*Guess-X)/2/Guess,
         not(equal(NewGuess,Guess)),
         !,
         mysqrt(X,NewGuess,Root).
      mysqrt(_,Guess,Guess).
      equal(X,Y):-
         X/Y>0.99999, 
         X/Y<1.00001.
   goal
      solve(1,2,1).
    Текст этой программы можно взять здесь.

    Чтобы решить квадратное уравнение, эта программа вычисляет квадратный корень из дискриминанта D. Программа вычисляет квадратные корни по итеративной формуле, где новое значение (NewGuess) квадратного корня от X может быть получено из предыдущего значения (Guess):

    NewGuess=Guess-(Guess*Guess-X)/2/Guess

    Каждая итерация немного приближается к квадратному корню от X. Когда условие equal(X,Y) удовлетворяется, дальнейшего приближения достичь нельзя - вычисление заканчивается. Теперь программа может решить квадратное уравнение, используя значения Xl и Х2

    X1=(-В+sqrtD)/(2*A)
    Х2=(-В-sqrtD)/(2*A)

    На следующем шаге мы рассмотрим сравнение символов, строк и идентификаторов.




Предыдущий шаг Содержание Следующий шаг