0

在递归中,方法调用自身。当有返回值时,我不关注它。例如,在 Chris Pine 的“学习编程”一书中,有一个关于阶乘的示例。

def factorial num 
  if num < 0
    return 'You cant\'t take the factorial of a negative number!'
  end
  if num <= 1
    1
  else 
    num * factorial(num-1)
  end
end 

如果我调用方法factorial(3),它将转到else代码部分,如下所示:

3 * factorial(3-1)

并且应该63*2=6. factorial(3-1)调用在递归中factorial传递的方法。, 因此和.2num = 22 * factorial(2-1)2*1=2

6我们从第一次运行代码中得到的结果会怎样?现在num = 1,看起来这将返回1并转到代码的末尾。但据我了解,我们仍然有62从以前的递归。我在这个假设中是否正确,因为当我们乘以时我们调用了阶乘函数num?有人可以帮助我更好地理解这一点吗?假设我们打电话factorial(10),这将如何解决?

4

3 回答 3

4

现在我们从第一次运行代码中得到的 6 会发生什么?

第一次运行没有 6 个;6只出现在最后。

这就是发生的事情:

factorial(3) → 3 * factorial(2)
factorial(3) → 3 * 2 * factorial(1)
factorial(3) → 3 * 2 * 1

您的函数中没有以前调用的“记忆”,每次调用 factorial() 时,它就像一个全新的函数;写成多个函数时更清楚吗?

def factorialof3
  3 * factorialof2
end

def factorialof2
  2 * factorialof1
end

def factorialof1
  1
end
于 2013-05-21T05:07:22.347 回答
1

Patrice 回答将其拆分为单独的函数很好,如果您有任何计算机科学背景,那么考虑一下可能在这里工作的数据结构也将有所帮助,主要是Stack

所以当你打电话时factorial(3)它会去那个else块并在另一个调用 factorial(2) 时“堆栈”

然后通过调用堆栈另一个factorial(1).

那时,因为num = 1,(递归必须始终有一个基本情况)factorial(1) 将返回 1。

然后由于堆栈,最后一个进是第一个出,所以 factorial(1) 将返回 1,这将“落”回factorial(2)调用,因为它是在 else 块中调用的,所以调用tofactorial(2-1)现在将被 1 替换,你将得到 2*1,我想现在你已经明白了

同样重要的是要注意,这个例子试图教你一般的递归,这个例子并不是真正地道的 ruby​​。作为评论发布的解决方案 alfasin 更像是它。

于 2013-05-21T05:17:21.150 回答
0

首先,您应该将您的替换return 'blabla'为 a raise 'blabla',因为您的函数返回的是数字,而不是字符串。

然后这样看

factorial(3)
  3 * factorial(2)
        2 * factorial(1)
              1  # no more recursion, let's go up replacing 
                 # the function calls by the returned value
            end
      end
end
# ↓
factorial(3)
  3 * factorial(2)
        2 * 1  # let's go up again !
      end
end
# ↓
factorial(3)
  3 * 2 # finally
end
# ↓
6
于 2013-05-21T05:29:41.883 回答