没有削减的Prolog二进制加法(!)

时间:2012-11-19 01:56:01

标签: binary prolog addition

我试图弄清楚如何将两个二进制数加在一起,表示为列表。例如: addNumbers([1,0,1],[1,1,0,0],X)。应该返回X = [1,0,0,0,1]。

我们不会大声使用剪切(!)来解决这个问题。所以我知道我必须实现各种加法器。现在我添加了用其所需谓词实现的数字:

addDigits(A,B,X,Y) :- myXor(A,B,X), myAnd(A,B,Y).

myAnd(A,B,R) :- A == 1, B == 1, R is 1.
myAnd(A,B,R) :- A == 0, B == 0, R is 0.
myAnd(A,B,R) :- A == 1, B == 0, R is 0.
myAnd(A,B,R) :- A == 0, B == 1, R is 0.
myOr(A,B,R) :- A == 0, B == 0, R is 0.
myOr(A,B,R) :- A == 0, B == 1, R is 1.
myOr(A,B,R) :- A == 1, B == 0, R is 1.
myor(A,B,R) :- A == 1, B == 1, R is 1.

这正确地返回X作为2个二进制数字的总和,Y作为进位。现在我知道我的加法器需要这个。现在实际实现addDigits是我被困的地方。这是我目前所拥有但不起作用的。注意:提示是LSB的开始,但我目前不这样做。

addNumbers([HA|TA],[HB|TB],X) :- adder(HA,HB,Cin,Sum,Cout,X),
    append(Sum, X, X),
    addNumbers(TA,TB,X).

adder(X,Y,Cin,Sum,Cout) :- addDigits(X,Y,Sum1,Carry1),
    addDigits(Sum1, Cin, Sum, Carry2),
    myOr(Carry1, Carry2, Cout).

任何帮助/建议将不胜感激。

干杯

1 个答案:

答案 0 :(得分:2)

你走得很好。您的主要问题是了解典型的Prolog递归。

但首先,你的二进制函数:它们是正确的,但它更容易,更可读(无论如何你都错过了这个):

myXor(1,0,1).
myXor(0,1,1).
myXor(1,1,0).
myXor(0,0,0).

在第四种情况下,myOr中存在拼写错误:您拼写为小写“o”。通过此定义,您的adder确实可以正常工作!

现在,关于递归:你真的需要从LSB开始,否则你甚至不知道要添加哪些位,因为数字不一定是相同的长度。幸运的是,您可以通过将呼叫包裹在reverse s:

中来轻松完成此操作
addNumbers(N1, N2, Sum) :- 
    reverse(N1, N12), 
    reverse(N2, N22),
    addNumbers(N12, N22, 0, [], Sum0),
    reverse(Sum0, Sum).

这是Prolog中非常常见的模式:addNumbers / 3调用addNumbers / 5,递归所需的参数更多。 “0”是初始进位,[]是结果的累加器。 这是addNumbers / 5,您的版本有一些更改:

addNumbers([HA|TA],[HB|TB],Cin,X0,X) :- 
    adder(HA,HB,Cin,Sum,Cout),
    append(X0, [Sum], X1),
    addNumbers(TA,TB,Cout,X1,X).

首先,请注意您需要在此处接收Cin作为输入参数!此外,我们将X0作为“累加器”变量,也就是说,每次递归调用它都会变长。最后的调用将产生结果,因此它可以使其成为输出变量。为此,您还需要基本案例:

addNumbers([],B,Cin,X0,X) :- % TODO: Respect Cin
    append(X0,B,X).
addNumbers(A,[],Cin,X0,X) :- % TODO: Respect Cin
    append(X0,A,X).

看看append的结果不是上面的X1(另一个中间变量),而是X?这是因为它的最终结果,它将与调用堆栈中的相同X统一,这样它就成为整个addNumbers / 5调用的输出!

我离开了它未完成,所以剩下一些(小)工作:基本情况需要考虑Cin ......

相关问题