通过使用sumInts方法了解scala替换模型

时间:2012-09-26 15:48:37

标签: scala recursion

我正在做一个scala课程,其中一个例子是sumInts函数,定义如下:

  def sumInts(a: Int, b: Int) : Int = 
    if(a > b) 0  
    else a + sumInts(a + 1 , b)

我试图通过在迭代时输出一些值来更好地理解这个函数:

class SumInts {
      def sumInts(a: Int, b: Int) : Int = 
        if(a > b) 0 else 
        {     
          println(a + " + sumInts("+(a + 1)+" , "+b+")")       
          val res1 = sumInts(a + 1 , b)
          val res2 = a
          val res3 = res1 + res2
          println("res1 is : "+res1+", res2 is "+res2+", res3 is "+res3)
          res3
        }
}

所以代码:

object SumIntsMain {

    def main(args: Array[String]) {

      println(new SumInts().sumInts(3 , 6));

  }

}

返回输出:

3 + sumInts(4 , 6)
4 + sumInts(5 , 6)
5 + sumInts(6 , 6)
6 + sumInts(7 , 6)
res1 is : 0, res2 is 6, res3 is 6
res1 is : 6, res2 is 5, res3 is 11
res1 is : 11, res2 is 4, res3 is 15
res1 is : 15, res2 is 3, res3 is 18
18

有人可以解释如何计算这些值。我已经尝试输出所有创建的变量,但仍然很困惑。

3 个答案:

答案 0 :(得分:6)

manual-human-tracer on:

return sumInts(3, 6) | a = 3, b = 6
3 > 6 ? NO
return 3 + sumInts(3 + 1, 6) | a = 4, b = 6
4 > 6 ? NO
return 3 + (4 + sumInts(4 + 1, 6)) | a = 5, b = 6
5 > 6 ? NO
return 3 + (4 + (5 + sumInts(5 + 1, 6))) | a = 6, b = 6
6 > 6 ? NO
return 3 + (4 + (5 + (6 + sumInts(6 + 1, 6)))) | a = 7, b = 6
7 > 6 ? YEEEEES (return 0)
return 3 + (4 + (5 + (6 + 0))) = return 18.

手动 - 人类追踪器关闭。

答案 1 :(得分:5)

要理解递归代码的作用,不必分析递归树。事实上,我认为这通常只是令人困惑。

假装它有效

让我们考虑一下我们要做的事情:我们希望将所有整数从a开始求和,直到某个整数b

  

a + sumInts(a + 1,b)

让我们假装sumInts(a + 1, b)实际上做了我们想要的事情:将整数从a + 1求助到b。如果我们接受这个是真理,很明显我们的函数会正确处理从ab的更大问题。因为很明显,总和中缺少的是附加术语a,只需添加即可。我们得出结论,它必须正常工作。

基础:基础案例

但是,这个sumInts()必须建立在某种基础上:基本情况,不涉及递归。

  

if(a> b)0

仔细观察我们的递归调用,我们可以看到它做出了某些假设:我们希望a低于b。这意味着总和将如下所示:a + (a + 1) + ... + (b - 1) + b。如果a大于b,则此总和自然会计算为0.

确保其有效

在递归调用保证中看到sumInts()总是将a增加1,我们实际上会在某个时刻触及基本情况。

进一步注意,最终将调用sumInts(b, b),我们现在可以验证代码是否有效:由于b不大于自身,因此将调用第二种情况:b + sumInts(b + 1, b) 。从这里开始,很明显这将评估为:b + 0,这意味着我们的算法可以正确地适用于所有值。

答案 2 :(得分:1)

您提到了替换模型,因此我们将其应用于您的sumInts方法:

我们首先调用sumInts(3,4)(你使用6作为第二个参数,但我选择了4,所以我可以输入更少),所以让我们用{代替{3}代替{4}代替a 1 {}在b的定义中。这给了我们:

sumInts

那么,结果会是什么?好吧,if(3 > 4) 0 else 3 + sumInts(3 + 1, 4) 显然是假的,所以最终结果将等于else子句,即3加上3 > 4的结果(4是sumInts(4, 4)的结果)。现在我们需要知道3+1的结果是什么。为此,我们可以再次替换(这次用4代替sumInts(4, 4)a):

b

好的,if(4 > 4) 0 else 4 + sumInts(4 + 1, 4) 的结果将是4加sumInts(4,4)的结果。那是什么sumInts(5,4)?替换者!

sumInts(5,4)

这次if条件为真,所以if(5 > 4) 0 else 5 + sumInts(5 + 1, 4) 的结果为0.所以现在我们知道sumInts(5,4)的结果必须是sumInts(4,4),这是4。 4 + 0的结果必须为sumInts(3,4),即7。