我一直在prolog中学习递归,它似乎有效,但输出的格式非常奇怪;
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
我很困惑为什么分钟有效,但时间却没有。 该程序应该将分钟转换为小时和分钟。 提前谢谢!
答案 0 :(得分: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系统中,您可能必须导入库才能在整数上使用此类关系。例如,在SICStus Prolog,YAP和SWI中,使用library(clpfd)
。
相反,您当前使用的谓词(=)/2
表示语法统一,并且不计算算术表达式。
答案 1 :(得分: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
。这在Prolog文档中描述:
H is H1 + 1
这将实际评估H1 + 1
,假设它是一个有效的算术表达式(在这种情况下),并且所有变量都用数值实例化。 Prolog中还有其他运算符将执行算术表达式评估:</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.