2017-02-19 27 views
2

Я изучаю рекурсию в прологе и, похоже, работает, но результат находится в очень странном формате;Пролог, возвращающий H = 0 + 1 + 1, а не H = 2

mins_to_hours(In, H, M):- 
    In < 60, 
    H is 0, 
    M is In. 
mins_to_hours(In, H, M):- 
    In > 59, 
    H = H1 + 1, 
    In1 = In - 60, 
    mins_to_hours(In1, H1, M). 

Является ли мой код и дал запрос, mins_to_hours(135, H, M). Отклик

H = 0+1+1, 
M = 15 

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

ответ

2

При анализе целых чисел используйте, например, предикат (#=)/2, чтобы выразить равенство арифметических выражений.

Например, с помощью GNU Prolog:

 
mins_to_hours(In, H, M):- 
    In #< 60, 
    H #= 0, 
    M #= In. 
mins_to_hours(In, H, M):- 
    In #> 59, 
    H #= H1 + 1, 
    In1 #= In - 60, 
    mins_to_hours(In1, H1, M). 

Таким образом, я просто с помощью (#=)/2 выразить равенство, (#<)/2 выразить "меньше, чем  ", и (#>)/2 выразить "больше чем".

Пример запроса и ответа:

 
| ?- mins_to_hours(135, H, M). 

H = 2 
M = 15 ? ; 

no 

Он также работает в других направлениях, например:

 
| ?- mins_to_hours(Mins, 2, 15). 

Mins = 135 ? ; 

no 

наиболее общий запрос тоже работает:

 
| ?- mins_to_hours(Mins, H, M). 

H = 0 
M = _#2(0..59) 
Mins = _#2(0..59) ? ; 

H = 1 
M = _#72(0..59) 
Mins = _#2(60..119) ? ; 

H = 2 
M = _#136(0..59) 
Mins = _#2(120..179) ? 

В других систем Prolog, вам, возможно, придется импортировать библиотеку для нас e такие отношения над целыми числами. Например, в SICStus Prolog, YAP и SWI используйте library(clpfd).

В отличие от этого, предикат (=)/2 вы используете Обозначает синтаксических   объединение и не оценки арифметических выражений.

1

@mat имеет правильный ответ относительно рассуждений по целым числам.

Причина, по которой вы видите H = 0+1+1, заключается в том, что в Prolog + это еще один функтор. То есть, H1 + 1 эквивалентен '+'(H1, 1), а оператор =/2 - не присвоение, как и на других языках. Это унификация терминов. Так сказать, H = H1 + 1 просто объединяетH с термином '+'(H1, 1) или H1 + 1. Если H1 унифицирован с 0, то H будет объединен с термином 0 + 1. Если позднее H1 объединяется с 0 + 1 и вы выполняете H = H1 + 1, то H будет иметь значение 0 + 1 + 1 и так далее.

Если вы хотите выполнить арифметическое выражение, вы можете использовать is/2. Это описано в документации Пролог:

H is H1 + 1 

Это будет на самом деле оценить H1 + 1 предполагая, что он является действительным арифметическое выражение (которое в данном случае) и все переменные экземпляра с числовыми значениями. В Прологе есть другие операторы, которые будут выполнять оценку арифметического выражения: </2, >/2, =:=/2 и т. Д., А также операторы CLP (FD), #=/2 и т. Д., Как описано в ответе @ mat. Все они описаны в документации Prolog.

И наоборот, вы используете is/2, где вы должны использовать унификацию. Это:

mins_to_hours(In, H, M):- 
    In < 60, 
    H is 0,   % 0 is a trivial expression and doesn't need evaluating 
    M is In.   % In is a trivial expression and doesn't need evaluating 

Должно быть написано как:

mins_to_hours(In, H, M):- 
    In < 60, 
    H = 0, 
    M = In. 

Или более кратко, как:

min_to_hours(In, 0, In) :- In < 60.