正如Simon Gibbons所解释的那样,您的代码中有
while n < 1:
而不是
while num > 1:
因此,您使用“小于”而不是“大于”,因此您的while语句中的测试将立即失败。但是,如果您将其更改为while n > 1:,它将永远循环,因为您从未在while循环内更改n的值。
Haresh Shyara发布了您的代码的已更正版本,如下所示:
def factorial(n):
result = 1
while n > 1:
result = result * n
n = n - 1
return result
请注意,此代码不会复制
n
到
num
,而是直接使用
n
。这不会影响您调用函数的参数,因为:
- Python整数是不可变的;
n = n - 1
实际上创建了一个名为n
的新本地对象。
我受到Frerich Raabe答案的启发,写了一个程序以更系统化的方式对这里提供的各种解决方案进行计时。我还包括了
math.factorial()
和一个简单的基于
for
循环的函数。
我稍微优化了调用
operator.mul
的函数,通过定义
mul = operator.mul
,但我必须向使用
reduce()
的那些函数提供一个初始参数1,以便它们不会在
factorial(0)
上失败(应返回1)。
我大致按速度从快到慢地排列了这些函数。
我刚刚增强了这个程序,使其更容易运行多个测试并添加新的要测试的函数。此外,在运行计时测试之前,它现在打印每个函数的简要描述,使用函数的docstring。并且在运行计时测试之前,它会验证每个函数计算正确的值。
''' Test and time various implementations of the factorial function
From https://dev59.com/aIfca4cB1Zd3GeqPnsyW
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:
try:
fname = func.func_name
fdoc = func.__doc__
except AttributeError:
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
结果一样,每个列表中最快的条目是重要的,较慢的条目应被忽略。
来自
timeit文档(由
Ffisegydd提供):
“...最低值给出了您的机器运行给定代码片段的下限;结果向量中的较高值通常不是由Python速度的可变性引起的,而是由其他进程干扰您的计时精度。因此,结果的
min()
可能是您唯一感兴趣的数字...”
n
,但是在循环中你只改变了result
和num
。这个循环将会运行 0 次或无限次。 - LeeNeverGupmath.factorial
要快得多。 - AncientSwordRage