2017-02-13 81 views
1

我从掌握Prolog的书中获得了以下Prolog,并且我试图学习一些简单的递归。了解序言中的简单递归

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

我不完全确定它为什么不起作用,我已经摆弄了好几个小时。任何帮助,甚至指向正确的方向我非常感谢。提前致谢。

+0

忘了提及它应该做什么...它应该将分钟转换为小时和分钟,例如,如果给了它140它应该返回H = 2 M = 20 – jdoggg

+0

您可以编辑您的问题进行更新。你应该把你的评论中的信息放入问题中。 –

回答

2

在这个例子中你面临的一个主要困难是所谓的模式的低级算术谓词。例如,让我们尝试最一般的查询与您发布的代码:

 
?- mins_to_hours(In, H, M). 
ERROR: Arguments are not sufficiently instantiated 

为了摆脱这个缺点,我第一次更换CLP低级谓词(FD)约束,这在所有主要的Prolog系统中都可用,并简化了代码的推理。

对于这一点,我只需更换(<)/2通过(#<)/2(is)/2(#=)/2等(根据您的Prolog的系统上,你也可能仍然必须导入此库):

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

现在,让我们再次尝试最一般的查询,所有的参数都是新鲜的变量

 
?- mins_to_hours(In, H, M). 
In = M, 
H = 0, 
M in inf..59 ; 
H = -1, 
In in 60..119, 
M+60#=In, 
M in 0..59 ; 
H = -2, 
In in 120..179, 
_5238+60#=In, 
_5238 in 60..119, 
M+60#=_5238, 
M in 0..59 . 

这里,似乎很奇怪,H可以假设为负值的值!

让我们尝试一些具体箱子:

 
?- mins_to_hours(30, H, M). 
H = 0, 
M = 30 ; 
false. 

这似乎仍然相当OK!

 
?- mins_to_hours(60, H, M). 
H = -1, 
M = 0 ; 
false. 

这似乎已经很多 OK!

通过一些练习,很容易看出原因:在第二个条款中,您无意中混淆了HH1的角色!假设我们写的第二句话是这样的:

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

然后我们得到:

 
?- mins_to_hours(60, H, M). 
H = 1, 
M = 0 ; 
false. 

而对于两个情况:

 
?- mins_to_hours(500, H, M). 
H = 8, 
M = 20 ; 
false. 

?- mins_to_hours(1000, H, M). 
H = 16, 
M = 40 ; 
false. 

似乎相当不错!

请注意,如果你坚持低级别的运算,可以没有,很容易纠正错误:使用谓词像(<)/2(is)/2需要你还要考虑到实际执行顺序的Prolog的,这是太几乎所有初学者都很难。我强烈建议您使用CLP(FD)约束,因为它们让您轻松尝试不同目标订单的效果,同时保持关系正确并且一般