2017-02-19 127 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序言:

 
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。如果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. 
相关问题