问题
编写一个程序,可以计算给定数字的阶乘。
假设将以下输入提供给程序:8
然后,输出应为:40320
我所编写的程序
n = int(input('请输入数字:')) #此处要注意,在获取输入的内容时都默认为是字符串类型,所以要转换为数值型才能在接下来的语句中调用
s = 1 #所s没有初始值,则无法在下面设置自身相乘
for m in range(n): #利用for循环实现不断相乘,range()函数得到的其实是一个iterable类型,在python里解释为可以迭代的对象,所以可以使用for来遍历产生的结果,使用list()将结果转化为列表类型。
s *= (m + 1)
print(s)
输入:8
输出结果:40320
原问题答案
def fact(x): #定义一个功能为计算阶乘的函数
if x == 0:
return 1
return x * fact(x - 1) #函数递归调用
x=int(input()) #获取输入值,注意转换为数值型
print(fact(x)) #调用fact()函数,传入参数为x
输入:8
输出结果:40320
在该答案中使用了函数的递归调用(这样一看我自己写的答案实在是,,,,,太低端了),那么函数的递归是什么呢?
函数递归调用
函数递归定义:在调用一个函数的过程中直接或间接的调用该函数本身,称之为递归调用。递归调用最多能调用999层,不然会出现栈溢出的问题。
递归分为两个重要的阶段: 递推+回溯
递推:函数不断减少问题规模直至最终的终止条件。(就是按照给定的条件不断地正向推算下去,先不用考虑返回值的问题,因为需要拿到最后一层的返回值才能够进行计算)
以此答案为例,递推就是指: return x * fact(x - 1) 这一句中,按照调用顺序正向推算,直到传入函数的值为(1-1)也就是0,此时符合if条件并执行if条件下的语句,:return 1,获得了最后的一层返回值:1,不再执行下面的调用语句,终止了循环,递推结束。
递推过程分解如下(此部分用于理解代码执行过程),输入8后:
def fact(x): #这是获得输入后,在函数外开始调用这个函数
if x == 0:
return 1
return 8 * fact(8 - 1) # fact(8 - 1)是在函数内对函数本身进行第一次调用
def fact(x):
if x == 0:
return 1
return 8 *7* fact(7 - 1) #7* fact(7 - 1)是调用fact(8 - 1)产生的值,并通过fact(7 - 1)在函数内对函数本身进行第二次调用
def fact(x): #第三次循环时
if x == 0:
return 1
return 8 *7*6* fact(6 - 1) #6* fact(6 - 1)是调用fact(7 - 1)产生的值,并通过fact(6 - 1)在函数内对函数本身进行第三次调用
'''往下以此类推'''
return 8 *7*6*5*4*3*2*1 fact(1 - 1) #为什么只分析到了这里呢?因为在fact(1 - 1)对函数进行调用时,相当于fact(0),在该函数内有条件:当x==0时,就直接返回值:1,语句不再往下执行,所以式子就截止到了这里。
回溯:拿到最终明确的值(就是最底层的值:1)后,返回给上次调用进行处理,直至初始层。(这一部分是反向推算计算值,就是从最底层获得的返回值开始,不断地将获得的值返回给上一级处理,得到最终结果)
回溯过程分解如下(此部分用于理解代码执行过程):
return 8 *7*6*5*4*3*2*1*1 #根据对递推过程的分析,我们得到这个结果式子,最后一个数字1是通过fact(1 - 1)调用函数本身返回的值,也就是我们说的拿到最终明确的值,计算顺序如下
return 8 *7*6*5*4*3*2*1#因为要从最终值开始不断地返回上一级进行计算,所以首先计算1*1并返回计算结果:1,这个式子中的1就是1*1得到
return 8 *7*6*5*4*3*2 #这个式子中的2是通过返回上一级计算也就是2*1得到返回结果2
return 8 *7*6*5*4*6 #这个式子中的6是通过返回上一级计算也就是3*2得到返回结果6
'''再往下以此类推'''
#在这一部分的if语句返回的值为:1,它不会影响计算的结果,所以在做这一类问题的时候都可以考虑使用1作为返回值
注意在Python:
1、递归调用必须有一个明确的结束条件(参考此例子中的if语句)。
2、在python中没有尾递归优化(python解释器不支持),递归调用的效率不高。
3、进入下一次递归时,问题的规模必须降低(在这个例子中我理解为数值是越来越小,循环次数越来越少,函数的处理越来越简单,其他函数中也是同理)。
持续更新中,如果存在哪些问题,希望大家能及时指出,我一定会及时修改