一个类Nat表示一个数字(n),它具有指向n-1数字的前置字段,如果pre为null则表示该数字为零。
public class Nat {
private final Nat pre;
public Nat (Nat pre) { this.pre = pre; }
public Nat () { this(null); }
public boolean isZero () { return pre == null; }
public Nat succ () { return new Nat(this); }
…
}
我必须添加一个添加两个数字的方法,我不明白这假设如何返回一个代表“this”和其他的总和的Nat!
public Nat plus (Nat other) {
if (other.isZero())
return this;
return succ().plus(other.pre);
}
我认为它创造了一个“Nats”,它始终指向这个(前)的第二个Nat。 有人可以帮帮我吗?
答案 0 :(得分:4)
好吧,如果this
代表n
而other
代表m
,那么计算n
+ m
相当于计算{{1} +} + n+1
,这正是m-1
返回的内容。
在递归结束时,第一个数字到达succ().plus(other.pre)
,第二个数字到达n+m
。这就是0
为真时返回this
的原因。
答案 1 :(得分:1)
您不会将数字直接存储在列表中并以递归方式创建:
为什么plus()有效:
现在我们可以看到添加x+y
可以更改为(x-1)+(y+1)
等,直到0 + (y + x)
。在您的代码中,您对添加本身并不感兴趣,但是您希望到达代表求和结果的Nat
。您可以使用上述转换以递归方式执行此操作,直到other
为0
- 这是您的基本情况,它只计算递归调用并确保您执行x
次。
示例:
[null -> Nat1(pre=null) -> Nat2(pre=Nat1) -> Nat3(pre=Nat2) -> Nat4(pre=Nat3) -> Nat5(pre=Nat5)]
我们假设您要添加3
和2
。首先,您从other=Nat2
开始,然后在Nat3
上调用它,这样您就可以Nat3's
获得Nat4
后继,并使用plus()
在other's
上调用Nat1
前导plus()
,仍然没有为零,因此您使用Nat4's
前身Nat5
呼叫Nat1's
后继(null
)上的this
,您点击你的基础案例并返回Nat5
,此时递归为{{1}}。
答案 2 :(得分:1)
基本上它展开了等式
n + k = (n + 1) + (k - 1)
直到k为零。在这个过程中会创建很多临时Nats,但最终结果是Nat,其他Nat加数为零:你在第一个Nat中积累了结果。记下所有调用的算法的简单执行,你会看到它。
示例:1 + 2
1.plus(2)
-- 1.succ().plus(1)
---- 1.succ().succ().plus(0)
------> 1.succ().succ() == 3
编辑:与其他帖子相反,我认为这是不严格来说是递归递归。实际上,不会在同一对象实例上始终调用plus()方法。但这种行为确实是递归的。那么这取决于你的定义
答案 3 :(得分:0)
这种递归在功能语言中更容易理解。
我确信其他帖子足够明确plus
(a+b
变为a+1+b-1
)。
必须明确的是与此部分有关:
public Nat (Nat pre) { this.pre = pre; }
...
public Nat succ () { return new Nat(this); }
调用succ()
时,它会返回一个新的Object,所以this
来自此处:
public Nat succ () { return new Nat(this); }
将来自pre
:
public Nat (Nat pre) { this.pre = pre; }
这就是succ
有效的原因,因为最后会有类似this.pre.pre....pre
的内容。
为了更好地理解,您可以输入(最终在方法中添加一些打印行):
public static void main(String[] args) {
System.out.println("==== A new number is 0 ====");
Nat n1 = new Nat(); // 0
System.out.println(n1.isZero()); // true
Nat n2 = new Nat(); // 0
System.out.println(n2.isZero()); // true
Nat sum = n1.plus(n2); // 0
System.out.println(sum.isZero()); // true
System.out.println(n2.isZero()); // true
System.out.println("==== Test succ and pre ====");
Nat one = n1.succ(); // 1
System.out.println(one.isZero()); // false
Nat two = one.plus(one); // 1 + 1
System.out.println(two.isZero()); // false
System.out.println(two.pre.isZero()); // false
System.out.println(two.pre.pre.isZero()); // true
}