我知道Prolog中有关于因子函数的问题。我在人们提供的答案中找到了许多代码。但我的问题是,我已经写了两个事实代码。第一个功能仅适用于fact(1,X),fact(2,X),fact(3,X)
。从4开始,它产生false
。我想知道这个函数背后的逻辑以及它为什么没有给出大数字的结果。
fact(1,1).
fact(N,F):-fact(N1,F1),N is N1+1,F is F1*N,!.
fact1(1,1).
fact1(N,F):-N>1,N1 is N-1,fact1(N1,F1),F is F1*N.
?- fact(2,X).
X = 2.
?- fact(3,X).
X = 6.
?- fact(4,X).
false.
?- fact(5,X).
false.
?- fact(15,X).
false.
fact1函数完美地给出答案,
?- fact1(5,X).
X = 120 ;
false.
?- fact1(50,X).
X = 30414093201713378043612608166064768844377641568960512000000000000 ;
我想知道fact()
函数在逻辑上有什么问题。你也可以对fact()
进行一些修改,使其有效。我怀疑它可能是因为剪切({{1他们说这是Prolog的风险目标。
答案 0 :(得分:3)
当我知道关于Prolog谓词的没有时,我总是问系统:
就Prolog而言,这意味着我会询问最常见的查询,其中每个参数都是一个新变量。
例如,在fact/2
的情况下,我会问:
?- fact(N, F).
在这个例子中,我精确地得到 2个解决方案:
N = F, F = 1 ; N = F, F = 2.
所以,系统告诉我:这个谓词实际上只有 2种可能性:一个N
为1,另一个N
为2。
另一方面,系统还告诉我有N
为3的解决方案:
?- fact(3, F). F = 6.
所以,我们可能首先要问:
这是什么?是否有2个解决方案或3个,甚至更多?
并且,进一步:
我们是否需要一个产生矛盾答案的谓词?
fact(4, _)
失败考虑以下一般谓词的骨架:
fact(N, F):- some_predicate(N1, F1), N #= N1+1, F #= F1*N, ...
在您的特定情况下,some_predicate/2
为fact/2
。我有概括您的具体代码段,以获得更一般的解释并避免可能出现的任何混淆仅因为您的具体案例巧合地涉及递归谓语。以下内容确定谓词是否递归:
如果您知道(我们现在这样做)some_predicate/2
只有N1
为1或2的解决方案,那么 N
不能为。
这解释逻辑,使用fact/2
的纯代数属性,为什么fact(4, _)
失败。
特别注意追踪执行是 所必需的。只需使用逻辑推理,我们就找到了为什么您的查询无法容纳。
!/0
,你喝醉了!我们先从您的版本中删除!/0
:
fact(1, 1). fact(N, F):- fact(N1, F1), N #= N1+1, F #= F1*N.
我们发现此修复了问题:
?- fact(N, F). N = F, F = 1 ; N = F, F = 2 ; N = 3, F = 6 ; N = 4, F = 24 ; etc.
按照这些答案,我们也得到:
?- fact(3, F). F = 6 .
作为回报,我们现在得到其他问题,但至少我们在答案中避免了具体的矛盾。
我建议你坚持使用Prolog的纯粹单调核心,从语言中获益最多。一旦你离开这个子集,关于你的程序的推理将变得非常困难,你将失去你几乎自动获得的最有价值的属性。请参阅logical-purity。