我有以下代码用于计算python中数字的阶乘。但我无法理解为什么我得到答案为1。 可以有人纠正我的代码。我想在不使用递归的情况下计算阶乘。
def factorial (n):
result =1
num = n
while n<1:
result = result * num
num = num -1
return result
factorial(5)
1
答案 0 :(得分:9)
while n < 1:
应该是
while num > 1:
答案 1 :(得分:6)
其他人指出你的代码有什么问题,但是我想指出一个factorial
函数真正适用于更具功能性(如:函数式编程)的解决方案;这样可以避免完全获得while
循环条件的问题,因为您根本没有任何循环。我们的洞察力是n
的阶乘是1..n
的乘积,使用Python的reduce
函数可以很容易地定义产品。为了避免失去性能,这是我的Python 2.7解释器为您的(固定)代码提供的内容:
python -m timeit -s "import original" "original.factorial(10)"
1000000 loops, best of 3: 1.22 usec per loop
更具说明性的更短版本(单行):
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
......唉,它慢了:
python -m timeit -s "import func1" "func1.factorial(10)"
1000000 loops, best of 3: 1.98 usec per loop
但是,使用xrange
代替range
和operator.mul
代替自定义lambda可以解决此问题:
import operator
def factorial(n):
return reduce(operator.mul, xrange(1, n+1))
对我而言,这比原始代码更快:
python -m timeit -s "import func2" "func2.factorial(10)"
1000000 loops, best of 3: 1.14 usec per loop
就个人而言,我会将reduce
调用因素分解,以使代码更清晰(代价是一点点性能):
import operator
def product(it):
return reduce(operator.mul, it)
def factorial(n):
return product(xrange(1, n+1))
我喜欢这个版本的快速和明确:因子被定义为范围[1..n + 1 [(即排除n + 1)的乘积。如果您尝试计算较大数字的阶乘,性能差异会变得更明显:
python -m timeit -s "import original" "original.factorial(30)"
100000 loops, best of 3: 5.25 usec per loop
VS
python -m timeit -s "import func3" "func3.factorial(30)"
100000 loops, best of 3: 3.96 usec per loop
答案 2 :(得分:4)
while 5 < 1
始终为false,因此会返回result = 1
。那是错的。
答案 3 :(得分:4)
让我们看看:
n=5
。n < 1
做事情。n
已经大于1
,它不会执行while
代码。result
,在定义的第一行设置为1
。答案 4 :(得分:3)
Simon Gibbons解释说,你的代码已经
了 while n < 1:
而不是
while num > 1:
因此,小于而不是大于,因此while
语句中的测试将立即失败。但是,如果您将其更改为while n > 1:
,它将永远循环,因为您永远不会更改n
循环中while
的值。
Haresh Shyara发布了您的代码的更正版本,转载于此处:
def factorial(n):
result = 1
while n > 1:
result = result * n
n = n - 1
return result
请注意,此代码并不需要将n
复制到num
- 它只是直接使用n
。这不会影响您使用因为
n = n - 1
实际上创建了一个名为n
的新本地对象。我受到Frerich Raabe的启发,他的答案是编写一个程序,以更系统的方式完成此处提供的各种解决方案的时间安排。我还包括math.factorial()
和一个简单的基于for
循环的函数,我只是把它放在一起。
我已经通过定义operator.mul
优化了稍微调用mul = operator.mul
的函数,但我必须为使用{{1}的函数提供initial
参数1这样他们就不会在reduce()
上失败(应该返回1)。
我大致订购了从最快到最慢的功能。
我刚刚增强了这个程序,使其更容易运行多个测试并添加新功能进行测试。此外,它现在使用函数的docstring打印每个函数的简短描述。在运行时序测试之前,它会验证每个函数是否计算出正确的值。
factorial(0)
<强>输出强>
#!/usr/bin/env python
''' Test and time various implementations of the factorial function
From https://stackoverflow.com/q/28475637/4014959
Written by PM 2Ring 2015.02.13
'''
import operator
import math
from timeit import Timer
factorial0 = math.factorial
def factorial0a(n):
''' call math.factorial '''
return math.factorial(n)
def factorial1(n):
''' for loop'''
p = 1
for i in xrange(2, n+1):
p *= i
return p
mul = operator.mul
def product(it):
return reduce(mul, it, 1)
def factorial2(n):
''' reduce with op.mul '''
return reduce(mul, xrange(1, n+1), 1)
def factorial3(n):
''' call product() '''
return product(xrange(1, n+1))
def factorial4(n):
''' while loop '''
result = 1
while n > 1:
result = result * n
n = n - 1
return result
def factorial4a(n):
''' while loop with assignment operators '''
result = 1
while n > 1:
result *= n
n -= 1
return result
def factorial5(n):
''' recursive '''
if n <= 1:
return 1;
else:
return n*factorial5(n-1)
def factorial6(n):
''' reduce with lambda '''
return reduce(lambda res, val: res*val, xrange(n, 0, -1), 1)
funcs = (
factorial0,
factorial0a,
factorial1,
factorial2,
factorial3,
factorial4,
factorial4a,
factorial5,
factorial6,
)
def verify(n):
''' Check that each function calculates the same result as math.factorial '''
r = xrange(n)
fac = [factorial0(i) for i in r]
rc = True
for func in funcs[1:]:
for i in r:
v = func(i)
if v != fac[i]:
print 'Error: %s(%d) returns %d instead of %d' % (func.func_name, i, v, fac[i])
rc = False
return rc
def time_test(arg=10, loops=100000, reps=3):
''' Print timing stats for all the factorial functions '''
print 'Arg = %d, Loops = %d, Repetitions = %d' % (arg, loops, reps)
for func in funcs:
#Get function name and docstring
try:
fname = func.func_name
fdoc = func.__doc__
except AttributeError:
#Math.factorial has no name, and we can't modify its docstring
fname = 'factorial0'
fdoc = ' math.factorial itself '
print '\n%s:%s' % (fname, fdoc)
t = Timer('%s(%d)' % (fname, arg), 'from __main__ import %s' % fname)
r = t.repeat(reps, loops)
r.sort()
print r
print '\n'
def main():
if not verify(100): exit(1)
time_test(arg=5, loops=500000, reps=4)
time_test(arg=10, loops=200000, reps=4)
time_test(arg=50, loops=100000, reps=4)
if __name__ == '__main__':
main()
与所有Arg = 5, Loops = 500000, Repetitions = 4
factorial0: math.factorial itself
[0.30838108062744141, 0.3119349479675293, 0.31210899353027344, 0.32166290283203125]
factorial0a: call math.factorial
[0.62141299247741699, 0.62747406959533691, 0.63309717178344727, 0.66500306129455566]
factorial1: for loop
[1.4656128883361816, 1.476855993270874, 1.4897668361663818, 1.5052030086517334]
factorial2: reduce with op.mul
[1.5841941833496094, 1.5868480205535889, 1.6007061004638672, 1.6253509521484375]
factorial3: call product()
[1.8745129108428955, 1.8750350475311279, 1.8822829723358154, 1.9097139835357666]
factorial4: while loop
[1.1264691352844238, 1.1348199844360352, 1.1348659992218018, 1.178135871887207]
factorial4a: while loop with assignment operators
[1.1867551803588867, 1.1881229877471924, 1.1893219947814941, 1.2020411491394043]
factorial5: recursive
[1.9756920337677002, 1.9862890243530273, 1.9910380840301514, 2.0284240245819092]
factorial6: reduce with lambda
[2.8342490196228027, 2.8369259834289551, 2.8390510082244873, 2.8969988822937012]
Arg = 10, Loops = 200000, Repetitions = 4
factorial0: math.factorial itself
[0.24756813049316406, 0.24919605255126953, 0.26395106315612793, 0.28582406044006348]
factorial0a: call math.factorial
[0.3732609748840332, 0.37482404708862305, 0.37592387199401855, 0.38288402557373047]
factorial1: for loop
[0.88677501678466797, 0.89632201194763184, 0.89948821067810059, 0.90272784233093262]
factorial2: reduce with op.mul
[0.89040708541870117, 0.89259791374206543, 0.89863204956054688, 0.90652203559875488]
factorial3: call product()
[1.0093960762023926, 1.031667947769165, 1.2325050830841064, 1.7492170333862305]
factorial4: while loop
[0.93423891067504883, 0.93978404998779297, 0.94000387191772461, 0.95153117179870605]
factorial4a: while loop with assignment operators
[0.97296595573425293, 0.97462797164916992, 0.98288702964782715, 1.0095341205596924]
factorial5: recursive
[1.6726200580596924, 1.6786048412322998, 1.691572904586792, 1.6946439743041992]
factorial6: reduce with lambda
[1.8484599590301514, 1.8502249717712402, 1.8615908622741699, 1.9228360652923584]
Arg = 50, Loops = 100000, Repetitions = 4
factorial0: math.factorial itself
[1.6450450420379639, 1.6641650199890137, 1.6790158748626709, 1.7192811965942383]
factorial0a: call math.factorial
[1.7563199996948242, 2.0039281845092773, 2.1530590057373047, 2.3621060848236084]
factorial1: for loop
[2.7895750999450684, 2.8117640018463135, 2.8381040096282959, 3.0019519329071045]
factorial2: reduce with op.mul
[2.4697721004486084, 2.4750289916992188, 2.4813871383666992, 2.5051541328430176]
factorial3: call product()
[2.4983038902282715, 2.4994339942932129, 2.5271379947662354, 2.5356400012969971]
factorial4: while loop
[3.6446011066436768, 3.650169849395752, 3.6579680442810059, 3.7304909229278564]
factorial4a: while loop with assignment operators
[3.7421870231628418, 3.7477319240570068, 3.7655398845672607, 3.7749569416046143]
factorial5: recursive
[5.523845911026001, 5.5555410385131836, 5.5760359764099121, 6.2132260799407959]
factorial6: reduce with lambda
[4.9984982013702393, 5.0106558799743652, 5.0363597869873047, 5.0808289051055908]
结果一样,每个列表中最快的条目是重要的条目,应忽略较慢的条目。
来自timeit docs(由Ffisegydd提供):
...最低值给出了机器速度的下限 运行给定的代码片段;结果向量中的值越高 通常不是由Python的速度变化引起的,而是由其他人引起的 过程干扰您的计时准确性。所以
timeit
结果可能是你应该感兴趣的唯一数字...
答案 5 :(得分:1)
您的代码不会进入while循环本身。将其从n<1
更改为n>1
。例如,如果找到5的阶乘,n&lt; 1将被视为5 <1,这是错误的。
答案 6 :(得分:1)
def factorial(n):
result = 1
while n > 1:
result = result * n
n = n - 1
return result
print factorial(5)
120
答案 7 :(得分:0)
试试这个,它更干净:
def factorial( n ):
if n <= 1:
return 1;
else:
return n*factorial(n-1)
这是一种解决问题的递归方法。
答案 8 :(得分:-1)
说到简短的 Pythonic 代码
def factorial(n):
return reduce(lambda res, val: res*val, xrange(n, 0, -1), 1)
对于那些不了解火山代码如何运作的人来说,这里有一个近似的结论:
''' Equivalent code by PM 2Ring '''
def f(res, val):
return res * val
def factorial(n):
res = 1
for val in xrange(n, 0, -1):
res = f(res, val)
return res