【译文】递归函数

定义

递归与无穷大有关。我知道递归与无穷大有关。我想我知道递归与无穷大有关。他确信我认为我知道递归与无穷大有关。我们怀疑他是否确定我认为我知道......

我们认为,你认为,我们现在说服了你,我们可以永远继续这个自然语言递归的例子。递归不仅是自然语言的一个基本特征,也是人类认知能力的一个基本特征。我们的思维方式是基于递归的思维过程。即使使用非常简单的语法规则,例如“英语句子包含主语和谓语,谓语包含动词、宾语和补语”,我们也可以展示自然语言的无限可能。

认知科学家和语言学家斯蒂芬·平克 (Stephen Pinker) 是这样说的:“有几千个名词可以填满主语,几千个动词可以填满谓语,人们已经有几百万种打开句子的方式。可能的组合很快地乘以难以想象的大数。事实上,句子的全部内容在理论上是无限的,因为语言规则使用了一种叫做递归的技巧。

递归规则允许一个短语包含自身的一个例子,如她认为他认为他们认为他们认为他知道等等,无穷无尽。如果句子的数量是无限的,那么可能的想法和意图的数量也是无限的,因为实际上每个句子都表达了不同的想法或意图。”1

我们必须停止在自然语言中使用递归的短途旅行,回到计算机科学和程序中的递归,最后回到编程语言 Python 中的递归。

形容词“递归”源于拉丁语动词“recurrere”,意思是“跑回去”。这就是递归定义或递归函数所做的:它在“跑回”或返回到自身。大多数学过数学、计算机科学或阅读有关编程的书的人都会遇到阶乘,它在数学术语中定义为

啊!= n * (n-1)!,如果 n > 1 且 0!= 1

由于其简单明了,它经常被用作递归的示例。

递归的定义

递归是一种对问题进行编程或编码的方法,其中函数在其主体中一次或多次调用自身。通常,它返回此函数调用的返回值。如果一个函数定义满足递归条件,我们称这个函数为递归函数。

终止条件:递归函数必须满足一个重要的条件才能在程序中使用:它必须终止。如果每次递归调用问题的解决方案都缩小并朝着基本情况移动,则递归函数将终止。基本情况是指无需进一步递归即可解决问题的情况。如果调用中没有满足基本情况,递归可能会以无限循环结束。

例子:

4!= 4 * 3!
3!= 3 * 2!
2!= 2 * 1

替换计算值给了我们以下表达式

4!= 4 * 3 * 2 * 1

换句话说,计算机科学中的递归是一种解决问题的方法,它基于解决同一问题的较小实例。

Python 中的递归函数

现在我们来在 Python 中实现阶乘。它就像数学定义一样简单而优雅。

def  factorial ( n ): 
    if  n  ==  0 : 
        return  1 
    else : 
        return  n  *  factorial ( n - 1 )

我们可以通过在前面的函数定义中添加两个 print() 函数来跟踪该函数的工作方式:

def  factorial ( n ): 
    print ( "factorial has been called with n = "  +  str ( n )) 
    if  n  ==  1 : 
        return  1 
    else : 
        res  =  n  *  factorial ( n - 1 ) 
        print ( "intermediate result for " ,  n ,  " * factorial("  , n - 1 ,  "): " , res )
        返回 res	

打印(阶乘(5 ))

输出:

阶乘已被调用,n = 5
阶乘已被调用,n = 4
阶乘已被调用,n = 3
阶乘已被调用,n = 2
阶乘已被调用,n = 1
2 * factorial( 1 ) 的中间结果:2
3 * factorial( 2 ) 的中间结果:6
4 * factorial( 3 ) 的中间结果:24
5 * factorial( 4 ) 的中间结果:120
120

让我们看一下阶乘函数的迭代版本。

def  iterative_factorial ( n ): 
    result  =  1 
    for  i  in  range ( 2 , n + 1 ): 
        result  *=  i 
    return  result


对于 范围(5 ):
    打印(我, iterative_factorial (我))

输出:

0 1
1 1
2 2
3 6
4 24

通常的做法是将 0 的阶乘函数扩展为参数。定义0!为 是有道理的1,因为只有零个对象的一个​​排列,即如果没有什么要排列,“一切”就留在原地。另一个原因是在一组 n 中选择 n 个元素的方法的数量计算为 n!除以 n! 的乘积!和0!。

为了实现这一点,我们所要做的就是改变 if 语句的条件:

def  factorial ( n ): 
    if  n  ==  0 : 
        return  1 
    else : 
        return  n  *  factorial ( n - 1 )

斐波那契数列

我们关于递归的论文现在将我们引向另一个有趣的递归案例。

向日葵、黄金比例、枞树球果、达芬奇密码、Tool 的歌曲“Lateralus”和右侧的图形有什么共同点?对,斐波那契数列。我们不介绍斐波那契数列,因为它们是递归函数的另一个有用示例。尝试为这个数字序列编写递归函数可能会导致程序效率低下。事实上,如此低效以至于它不会有用。我们介绍斐波那契数列是为了向您展示递归的陷阱。

斐波那契正方形

斐波那契数是以下整数值序列的数字:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

斐波那契数列定义为:

Fn=Fn-+Fn-2

和 F0=0 和 F1=1

斐波那契数列以比萨的数学家列奥纳多 (Leonardo of Pisa) 的名字命名,他更为人所知的是斐波那契。在他的书“Liber Abaci”(出版于 1202 年)中,他介绍了这个序列作为处理兔子的练习。他的斐波那契数列从 F1 = 1 开始,而在现代数学中,该序列从 F0 = 0 开始。但这对序列的其他成员没有影响。

斐波那契数是人工兔子种群的结果,满足以下条件:

  • 一对刚出生的兔子,一公一母,建立初始种群
  • 这些兔子可以在一个月大的时候交配,这样在第二个月末,雌性就可以生育另一对兔子
  • 这些兔子是不朽的
  • 从第二个月开始,一对交配的一对总是每个月产生一对新的(一男一女)

斐波那契数是n几个月后兔子对的数量,即 10 个月后我们将有F10 兔子。

斐波那契数列很容易写成 Python 函数。它或多或少是数学定义中的一对一映射:

def  fib ( n ): 
    if  n  ==  0 : 
        return  0 
    elif  n  ==  1 : 
        return  1 
    else : 
        return  fib ( n - 1 )  +  fib ( n - 2 )

迭代解决方案也很容易编写,尽管递归解决方案看起来更像定义:

def  fibi ( n ): 
    old ,  new  =  0 ,  1 
    if  n  ==  0 : 
        return  0 
    for  i  in  range ( n - 1 ): 
        old ,  new  =  new ,  old  +  new 
    return  new

我们将编写一个名称fibonacci包含函数fibfibi. 为此,您必须将以下代码复制到名为 fibonacci0.py 的文件中:

""" 包含斐波那契函数的递归和迭代实现的
模块该模块的目的在于展示斐波那契函数的纯递归实现的低效率!"""

def  fib ( n ): 
    """ 斐波那契函数的递归版本 """ 
    if  n  ==  0 : 
        return  0 
    elif  n  ==  1 : 
        return  1 
    else : 
        return  fib ( n - 1 )  +  fib ( n - 2 )
    
def  fibi ( n ): 
    """ 斐波那契函数的迭代版本 """ 
    old ,  new  =  0 ,  1 
    if  n  ==  0 : 
        return  0 
    for  i  in  range ( n - 1 ): 
        old ,  new  =  new ,  old  +返回

输出:

覆盖 fibonacci0.py

如果您检查函数 fib() 和 fibi(),您会发现迭代版本 fibi() 比递归版本 fib() 快很多。为了了解这“快得多”可以达到多少,我们编写了一个脚本,它使用 timeit 模块来测量调用。为此,我们将 fib 和 fibi 的函数定义保存在文件 fibonacci.py 中,我们可以在下面的程序 (fibonacci_runit.py) 中导入该文件:

 timeit 导入 计时器

t1  =  Timer ( "fib(10)" , "from fibonacci import fib" )

对于 范围(1 , 20 ):
    CMD  =  “FIB(”  +  STR (我) +  “)” 
    T1  = 定时器(CMD , “从进口斐波纳契FIB” )
    TIME1  =  T1 timeit ( 3 ) 
    cmd  =  "fibi("  +  str ( i )  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值