这是我在Prolog中创建乘法运算符的尝试。
times1(X,Y,Z) :- Z=X*Y.
但它不起作用,我不知道为什么。谁能认出这个问题?
times1(0,Y,0):-!.
times1(X,0,0):-!.
times1(X,Y,Z):- X<0,Y<0,!, times1(-X,-Y,Z).
times1(X,Y,Z):- X>0,!,times1(X-1,Y,Z1),Z is Z1+Y.
times1(X,Y,Z):- X<0,Y>0,times1(Y,X,Z).
第二次尝试:
times1(0,ֹ_,0):-!.
times1(_,0,0):-!.
times1(X,Y,Z):- X<0,Y=\=0,X1 is -X, times1(X1,Y,Z1), Z is -Z1.
times1(X,Y,Z):- X>0,Y=\=0, X2 is X-1, times1(X2,Y,Z1),Z is Z1+Y.
仍然不起作用......
答案 0 :(得分:3)
在你的第一个解决方案中:
times1(X,Y,Z) :- Z=X*Y.
问题在于使用统一而不是表达评估。使用is/2
进行表达式评估:
times1(X,Y,Z) :- Z is X*Y.
在第二个解决方案中:
times1(0,Y,0):-!.
times1(X,0,0):-!.
times1(X,Y,Z):- X<0,Y<0,!, times1(-X,-Y,Z).
times1(X,Y,Z):- X>0,!,times1(X-1,Y,Z1),Z is Z1+Y.
times1(X,Y,Z):- X<0,Y>0,times1(Y,X,Z).
在表达式times1(X-1,Y,Z1)
中,Prolog在将其用作递归调用的参数之前不会评估X-1
。您需要明确地执行此操作:X1 is X-1, times1(X1,Y,Z1)
。
此外,你不需要这么多削减。例如,由于您已经检查了其他谓词子句中X
的{{1}}和Y
条件,因此基本情况可能只是:
0
您无需同时检查times1(0, _, 0). % 0 times anything is 0
times1(_, 0, 0). % Anything times 0 is 0
和X
为否定因为Y
,如果X*Y
为否定,则可能只有Y
个无论X
的符号如何,Y
值都会加在一起。然后,在否定Y
得到结果之后,你仍然需要否定最终的总和(以补偿否定的X
):
X
除了times1(X, Y, Z) :- X < 0, Y =\= 0, times1(-X, Y, Z1), Z is -Z1.
times1(X, Y, Z) :- X > 0, Y =\= 0, X1 is X-1, times1(X1, Y, Z1), Z is Z1+Y.
和Y < 0
案例已合并为Y > 0
之外,这几乎与您所拥有的一样,我对{{1}进行了额外检查在Y =\= 0
案例中避免削减,最后Y =\= 0
补偿否定X > 0
。
请注意,Z is -Z1
无需先执行X
即可运行,因为当times1(-X,Y,Z1)
传递给X1 is -X
时,-X
首先评估times1
或{{ 1}}将评估times1
的表达式,因此X < 0
将根据需要进行评估。虽然首先做X > 0
并且不做出假设仍然可能更安全。所以第一个条款将成为:
X
测试:
-
将X1 is -X
与times1(X, Y, Z) :- X < 0, Y =\= 0, X1 is -X, times1(X1, Y, Z1), Z is -Z1.
相乘会显示两个解决方案,因为它匹配两个案例。如果需要,可以使用原始解决方案中的方法消除切割,或者可以调整谓词逻辑,以便强制执行非重叠的情况。