用Python计算阶乘 - 迭代和递归

461 阅读6分钟

简介

根据定义,阶乘是一个正整数与所有小于或等于该数字的正整数的乘积。换句话说,得到一个数字的阶乘意味着将该数字以下的所有整数相乘,直至1。

根据惯例,**0!**也等于1。

阶乘是由整数表示的,后面有一个感叹号。

**5!**表示一个 阶乘.

为了计算这个阶乘,我们把这个数字与比它小的每个整数相乘,直到达到1。

5! = 5 * 4 * 3 * 2 * 1
5! = 120

牢记这些规则,在本教程中,我们将学习如何用Python计算整数的阶乘,使用循环和递归。让我们从使用循环来计算阶乘开始。

使用循环计算阶乘

我们可以使用while 循环和for 循环来计算阶乘。两者的一般过程都很相似。我们所需要的是一个参数作为输入和一个计数器。

让我们从for 循环开始。

def get_factorial_for_loop(n):
    result = 1
    if n > 1:
        for i in range(1, n+1):
            result = result * i
        return result
    else:
        return 'n has to be positive'

你可能已经注意到,我们是从1开始计数的,n ,而阶乘的定义是从_给定的数字到1_。但从数学上讲。

1 \* 2 \* 3 \* 4 ...n = n \* (n-1) \* (n-2) \* (n-3) \* (n-4) ...\* (n - (n-1)) $ $ > 为了简化,`(n - (n-1))` 将永远等于**1**。 这意味着,我们向哪个方向计数并不重要。它可以从**1**开始,向`n` ,也可以从`n` ,向**1**减少。现在已经清楚了,让我们开始分解我们刚刚写的函数。 我们的函数接收了一个参数`n` ,它表示我们要计算的阶乘的数字。首先,我们定义一个名为`result` 的变量,并将`1` 作为一个值分配给它。 > 你问为什么要赋值**1**而不是**0**? 因为如果我们给它赋值为**0**,那么接下来所有与**0**的乘法,自然会产生一个巨大的**0**。 然后我们在`1` 到`n+1` 的范围内开始我们的`for` 循环。记住,Python的范围将在第二个参数之前停止。为了把最后一个数字也包括在内,我们简单地增加一个额外的`1` 。 在`for` 循环中,我们将`result` 的当前值与我们的索引`i` 的当前值相乘。 最后,我们返回`result` 的最终值。让我们测试一下我们的函数打印出的结果。 ``` inp = input("Enter a number: ") inp = int(inp) print(f"The result is: {get_factorial_for_loop(inp)}") ``` > 如果你想阅读更多关于如何获得用户输入的信息,请阅读我们的《[在Python中获得用户输入](https://stackabuse.com/getting-user-input-in-python/)》。 它将提示用户进行输入。我们用`4` 来试试。 ``` Enter a number: 4 The result is: 24 ``` 你可以用计算器来验证这个结果。 **4!**是`4 * 3 * 2 * 1` ,结果是**24**。 现在让我们看看如何使用`while` 循环计算阶乘。下面是我们修改后的函数。 ``` def get_factorial_while_loop(n): result = 1 while n > 1: result = result * n n -= 1 return result ``` 这与`for` 循环很相似。除了这次我们从`n` 向**1**移动,更接近数学定义,但在给定w的函数方面是一样的。 让我们测试一下我们的函数。 ``` inp = input("Enter a number: ") inp = int(inp) print(f"The result is: {get_factorial_while_loop(inp)}") ``` 我们再一次输入4作为输入。 ``` Enter a number: 4 The result is: 24 ``` 虽然计算的结果是`4 * 3 * 2 * 1` ,但最后的结果和之前的一样。 使用循环计算阶乘是很容易的。现在让我们来看看如何使用递归函数计算阶乘。 ### 使用递归计算阶乘 递归函数是一个可以_调用自己的_函数。一开始听起来可能有点吓人,但跟着我们,你会发现递归函数很容易理解。 一般来说,每个递归函数都有两个主要组成部分:一个**基例**和一个递**归步骤**。 基准案例是问题的最小的实例。同时也是一个断点,一个将返回一个值并将_走出_递归的案例。就阶乘函数而言,基例是指我们返回阶乘的最后一个元素,也就是**1**。 > 如果没有基数情况或基数情况不正确,你的递归函数就会无限地运行,导致溢出。 递归步骤--顾名思义--是函数的递归部分,整个问题在这里被转化为更小的东西。如果递归步骤不能缩小问题,那么再次递归可以无限地运行。 考虑一下阶乘的递归部分。 * **5!**是`5 * 4 * 3 * 2 * 1` 。 但我们也知道,。 * `4 * 3 * 2 * 1` _是_ **4!**。 换句话说,**5!**是`5 * 4!` ,而**4!**是`4 * 3!` ,以此类推。 > 所以我们可以说,`n! = n * (n-1)!` 。这将是我们的阶乘的递归步骤! 阶乘的递归在达到**1**时结束。这将是我们的**基本情况**。如果`n` 是`1` 或更少,我们将返回`1` ,涵盖零输入。 让我们看一下我们的递归阶乘函数。 ``` def get_factorial_recursively(n): if n <= 1: return 1 else: return n * get_factorial_recursively(n-1) ``` 正如你所看到的,`if` 块体现了我们的**基本情况**,而`else` 块涵盖了递归的**步骤**。 让我们测试一下我们的函数。 ``` inp = input("Enter a number: ") inp = int(inp) print(f"The result is: {get_factorial_recursively(inp)}") ``` 这次我们将输入3作为输入。 ``` Enter a number:3 The result is: 6 ``` 我们得到同样的结果。但是这一次,引擎盖下的情况相当有趣。 你看,当我们输入时,该函数将检查`if` ,由于3大于1,它将跳到`else` 块。在这个块中,我们看到`return n * get_factorial_recursively(n-1)` 。 > 我们暂时知道`n` 的当前值,它是`3` ,但`get_factorial_recursively(n-1)` 仍需计算。 然后程序再次调用同一个函数,_但_这次我们的函数以**2**作为参数。它检查了`if` 块,然后跳到`else` 块,再次遇到最后一行。现在,`n` 的当前值是`2` ,但程序仍然必须计算`get_factorial_recursively(n-1)` 。 所以它再次调用该函数,但这次`if` 块,或者说,基类成功地返回了1,并从递归中脱离出来。 按照同样的模式往上走,它返回每个函数的结果,将当前的结果与之前的`n` ,并返回给之前的函数调用。换句话说,我们的程序首先到达阶乘的底部(也就是1),然后一路向上,同时在每一步上进行乘法。 同时从调用堆栈中逐一删除函数,直到返回`n * (n-1)` 的最终结果。 这一般是递归函数的工作方式。一些更复杂的问题可能需要更深层次的递归,有一个以上的基例或一个以上的递归步骤。但是现在,这个简单的递归已经足够解决我们的阶乘问题了! > 如果你想了解更多关于Python中的递归,请阅读我们的《[了解Python中的递归指南》](https://stackabuse.com/understanding-recursive-functions-with-python/)! ### 结语 在这篇文章中,我们介绍了如何使用`for` 和`while` 循环来计算阶乘。我们还学习了什么是递归,以及如何使用递归计算阶乘。 如果你喜欢递归并想进行更多的练习,可以尝试用递归来计算斐波那契数列如果你对我们的文章有任何问题或想法,欢迎在评论区分享。