Prolog返回H = 0 + 1 + 1而不是H = 2

时间:2017-02-19 17:57:04

标签: prolog

我一直在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

我很困惑为什么分钟有效,但时间却没有。 该程序应该将分钟转换为小时和分钟。 提前谢谢!

2 个答案:

答案 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。如果H10统一,则H将与术语0 + 1统一。如果稍后H10 + 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.